home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / WaveTableWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  72.9 KB  |  2,430 lines  |  [TEXT/KAHL]

  1. /* WaveTableWindow.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "WaveTableWindow.h"
  31. #include "MainWindowStuff.h"
  32. #include "CodeCenter.h"
  33. #include "WaveTableList.h"
  34. #include "TextEdit.h"
  35. #include "IconButton.h"
  36. #include "Scroll.h"
  37. #include "SimpleButton.h"
  38. #include "SampleView.h"
  39. #include "WindowDispatcher.h"
  40. #include "WaveTableObject.h"
  41. #include "Memory.h"
  42. #include "Numbers.h"
  43. #include "Array.h"
  44. #include "DataMunging.h"
  45. #include "EditImages.h"
  46. #include "GrowIcon.h"
  47. #include "Main.h"
  48. #include "StringDialog.h"
  49. #include "FindDialog.h"
  50. #include "GlobalWindowMenuList.h"
  51. #include "WaveTableStorage.h"
  52. #include "WaveTableStorageDisplay.h"
  53. #include "SoundOutput.h"
  54. #include "Alert.h"
  55. #include "NumberDialog.h"
  56. #include "WaveTableSizeDialog.h"
  57. #include "CompilerRoot.h"
  58. #include "PcodeObject.h"
  59. #include "PcodeStack.h"
  60. #include "PcodeSystem.h"
  61. #include "FunctionCode.h"
  62.  
  63.  
  64. #define PAGEINCREMENT (1)
  65.  
  66.  
  67. #define EIGHTBITSHIFTFACTOR (18)
  68. #define SIXTEENBITSHIFTFACTOR (10)
  69.  
  70.  
  71. #define WINDOWXSIZE (420)
  72. #define WINDOWYSIZE (300)
  73.  
  74. #define NAMEEDITX (80)
  75. #define NAMEEDITY (1)
  76. #define NAMEEDITWIDTH (80)
  77. #define NAMEEDITHEIGHT (19)
  78.  
  79. #define NAMEX (3)
  80. #define NAMEY (NAMEEDITY + 3)
  81.  
  82. #define FRAMEEDITX (NAMEEDITX)
  83. #define FRAMEEDITY (NAMEEDITY + NAMEEDITHEIGHT + 3)
  84. #define FRAMEEDITWIDTH (NAMEEDITWIDTH)
  85. #define FRAMEEDITHEIGHT (NAMEEDITHEIGHT)
  86.  
  87. #define FRAMEX (NAMEX)
  88. #define FRAMEY (FRAMEEDITY + 3)
  89.  
  90. #define TABLESEDITX (FRAMEEDITX)
  91. #define TABLESEDITY (FRAMEEDITY + FRAMEEDITHEIGHT + 3)
  92. #define TABLESEDITWIDTH (FRAMEEDITWIDTH)
  93. #define TABLESEDITHEIGHT (FRAMEEDITHEIGHT)
  94.  
  95. #define TABLESX (FRAMEX)
  96. #define TABLESY (TABLESEDITY + 3)
  97.  
  98. #define BITS8BUTTONX (10)
  99. #define BITS8BUTTONY (TABLESEDITY + TABLESEDITHEIGHT + 5)
  100. #define BITS8BUTTONWIDTH (32)
  101. #define BITS8BUTTONHEIGHT (32)
  102.  
  103. #define BITS16BUTTONX (BITS8BUTTONX + BITS8BUTTONWIDTH + 1)
  104. #define BITS16BUTTONY (BITS8BUTTONY)
  105. #define BITS16BUTTONWIDTH (BITS8BUTTONWIDTH)
  106. #define BITS16BUTTONHEIGHT (BITS8BUTTONHEIGHT)
  107.  
  108. #define TESTATTACKDURATIONX (TABLESEDITX)
  109. #define TESTATTACKDURATIONY (BITS16BUTTONY + BITS16BUTTONHEIGHT + 5)
  110. #define TESTATTACKDURATIONWIDTH (TABLESEDITWIDTH)
  111. #define TESTATTACKDURATIONHEIGHT (TABLESEDITHEIGHT)
  112.  
  113. #define TESTATTACKX (TABLESX)
  114. #define TESTATTACKY (TESTATTACKDURATIONY + 3)
  115.  
  116. #define TESTDECAYDURATIONX (TESTATTACKDURATIONX)
  117. #define TESTDECAYDURATIONY (TESTATTACKDURATIONY + TESTATTACKDURATIONHEIGHT + 3)
  118. #define TESTDECAYDURATIONWIDTH (TESTATTACKDURATIONWIDTH)
  119. #define TESTDECAYDURATIONHEIGHT (TESTATTACKDURATIONHEIGHT)
  120.  
  121. #define TESTDECAYX (TESTATTACKX)
  122. #define TESTDECAYY (TESTDECAYDURATIONY + 3)
  123.  
  124. #define TESTFREQUENCYX (TESTDECAYDURATIONX)
  125. #define TESTFREQUENCYY (TESTDECAYDURATIONY + TESTDECAYDURATIONHEIGHT + 3)
  126. #define TESTFREQUENCYWIDTH (TESTDECAYDURATIONWIDTH)
  127. #define TESTFREQUENCYHEIGHT (TESTDECAYDURATIONHEIGHT)
  128.  
  129. #define TESTFREQX (TESTDECAYX)
  130. #define TESTFREQY (TESTFREQUENCYY + 3)
  131.  
  132. #define TESTSAMPLINGRATEX (TESTFREQUENCYX)
  133. #define TESTSAMPLINGRATEY (TESTFREQUENCYY + TESTFREQUENCYHEIGHT + 3)
  134. #define TESTSAMPLINGRATEWIDTH (TESTFREQUENCYWIDTH)
  135. #define TESTSAMPLINGRATEHEIGHT (TESTFREQUENCYHEIGHT)
  136.  
  137. #define TESTSAMPLX (TESTFREQX)
  138. #define TESTSAMPLY (TESTSAMPLINGRATEY + 3)
  139.  
  140. #define TESTBUTTONX (10)
  141. #define TESTBUTTONY (TESTSAMPLINGRATEY + TESTSAMPLINGRATEHEIGHT + 5)
  142. #define TESTBUTTONWIDTH (80)
  143. #define TESTBUTTONHEIGHT (21)
  144.  
  145. #define EXPRESSIONEDITX (-1)
  146. #define EXPRESSIONEDITWIDTH(WindowWidth) ((WindowWidth) + 2)
  147. #define EXPRESSIONEDITHEIGHT (80)
  148. #define EXPRESSIONEDITY(WindowHeight) ((WindowHeight) - EXPRESSIONEDITHEIGHT + 1)
  149.  
  150. #define WAVEFORMVIEWX (NAMEEDITX + NAMEEDITWIDTH + 10)
  151. #define WAVEFORMVIEWY (-1)
  152. #define WAVEFORMVIEWWIDTH(WinWidth) ((WinWidth) - WAVEFORMVIEWX + 1)
  153. #define WAVEFORMVIEWHEIGHT(WinHeight) (EXPRESSIONEDITY(WinHeight) - WAVEFORMVIEWY - 16)
  154.  
  155. #define TABLESCROLLY(WinHeight) (WAVEFORMVIEWY + WAVEFORMVIEWHEIGHT(WinHeight) - 1)
  156.  
  157.  
  158. struct WaveTableWindowRec
  159.     {
  160.         MainWindowRec*            MainWindow;
  161.         CodeCenterRec*            CodeCenter;
  162.         WaveTableListRec*        WaveTableList;
  163.         WaveTableObjectRec*    WaveTableObject;
  164.  
  165.         WaveTableStorDispRec*    WaveTableData;
  166.         MyBoolean                        WaveDataModified;
  167.         WaveTableStorDispRec*    UndoBackupWaveTable;
  168.  
  169.         WinType*                        ScreenID;
  170.         TextEditRec*                NameEdit;
  171.         TextEditRec*                FunctionEdit;
  172.         TextEditRec*                NumFramesEdit;
  173.         TextEditRec*                NumTablesEdit;
  174.         TextEditRec*                TestAttackDuration;
  175.         TextEditRec*                TestDecayDuration;
  176.         TextEditRec*                TestFrequency;
  177.         TextEditRec*                TestSamplingRate;
  178.         TextEditRec*                ActiveTextEdit;
  179.         SimpleButtonRec*        TestButton;
  180.         IconButtonRec*            Bits8Button;
  181.         IconButtonRec*            Bits16Button;
  182.         ScrollRec*                    TableScroll;
  183.         long                                CurrentlyVisibleTable;
  184.         GenericWindowRec*        MyGenericWindow; /* how the window event dispatcher knows us */
  185.         MenuItemType*                MyMenuItem;
  186.     };
  187.  
  188.  
  189. /* create a new wave table window. */
  190. WaveTableWindowRec*    NewWaveTableWindow(struct MainWindowRec* MainWindow,
  191.                                             struct WaveTableObjectRec* WaveTableObject,
  192.                                             struct CodeCenterRec* CodeCenter,
  193.                                             struct WaveTableListRec* WaveTableList,
  194.                                             struct WaveTableStorageRec* WaveData,
  195.                                             OrdType WinX, OrdType WinY, OrdType WinWidth, OrdType WinHeight)
  196.     {
  197.         WaveTableWindowRec*        Window;
  198.         char*                                    StringTemp;
  199.         long                                    Scan;
  200.         long                                    Limit;
  201.  
  202.         CheckPtrExistence(MainWindow);
  203.         CheckPtrExistence(WaveTableObject);
  204.         CheckPtrExistence(CodeCenter);
  205.         CheckPtrExistence(WaveTableList);
  206.         CheckPtrExistence(WaveData);
  207.  
  208.         /* deal with window placement */
  209.         if ((WinWidth < 100) || (WinHeight < 100) || ((eOptionKey & CheckModifiers()) != 0))
  210.             {
  211.                 WinX = 1 + WindowOtherEdgeWidths(eDocumentWindow);
  212.                 WinY = 1 + WindowTitleBarHeight(eDocumentWindow);
  213.                 WinWidth = WINDOWXSIZE;
  214.                 WinHeight = WINDOWYSIZE;
  215.             }
  216.         MakeWindowFitOnScreen(&WinX,&WinY,&WinWidth,&WinHeight);
  217.  
  218.         Window = (WaveTableWindowRec*)AllocPtrCanFail(sizeof(WaveTableWindowRec),
  219.             "WaveTableWindowRec");
  220.         if (Window == NIL)
  221.             {
  222.              FailurePoint1:
  223.                 return NIL;
  224.             }
  225.         Window->MainWindow = MainWindow;
  226.         Window->WaveTableObject = WaveTableObject;
  227.         Window->CodeCenter = CodeCenter;
  228.         Window->WaveTableList = WaveTableList;
  229.  
  230.         Window->ScreenID = MakeNewWindow(eDocumentWindow,eWindowClosable,
  231.             eWindowZoomable,eWindowResizable,WinX,WinY,WinWidth,WinHeight,
  232.             (void (*)(void*))&WaveTableWindowUpdator,Window);
  233.         if (Window->ScreenID == 0)
  234.             {
  235.              FailurePoint2:
  236.                 ReleasePtr((char*)Window);
  237.                 goto FailurePoint1;
  238.             }
  239.  
  240.         Window->NameEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  241.             GetScreenFont(),9,NAMEEDITX,NAMEEDITY,NAMEEDITWIDTH,NAMEEDITHEIGHT);
  242.         if (Window->NameEdit == NIL)
  243.             {
  244.              FailurePoint3:
  245.                 KillWindow(Window->ScreenID);
  246.                 goto FailurePoint2;
  247.             }
  248.         StringTemp = WaveTableObjectGetNameCopy(WaveTableObject);
  249.         if (StringTemp == NIL)
  250.             {
  251.              FailurePoint4:
  252.                 DisposeTextEdit(Window->NameEdit);
  253.                 goto FailurePoint3;
  254.             }
  255.         TextEditNewRawData(Window->NameEdit,StringTemp,"\x0a");
  256.         ReleasePtr(StringTemp);
  257.         TextEditHasBeenSaved(Window->NameEdit);
  258.  
  259.         Window->FunctionEdit = NewTextEdit(Window->ScreenID,eTEVScrollBar | eTEHScrollBar,
  260.             GetMonospacedFont(),9,EXPRESSIONEDITX,EXPRESSIONEDITY(WinHeight),
  261.             EXPRESSIONEDITWIDTH(WinWidth),EXPRESSIONEDITHEIGHT);
  262.         if (Window->FunctionEdit == NIL)
  263.             {
  264.              FailurePoint5:
  265.                 goto FailurePoint4;
  266.             }
  267.         StringTemp = WaveTableObjectGetFormulaCopy(WaveTableObject);
  268.         SetTextEditTabSize(Window->FunctionEdit,MainWindowGetTabSize(MainWindow));
  269.         if (StringTemp == NIL)
  270.             {
  271.              FailurePoint6:
  272.                 DisposeTextEdit(Window->FunctionEdit);
  273.                 goto FailurePoint5;
  274.             }
  275.         TextEditNewRawData(Window->FunctionEdit,StringTemp,"\x0a");
  276.         ReleasePtr(StringTemp);
  277.         TextEditHasBeenSaved(Window->FunctionEdit);
  278.         SetTextEditAutoIndent(Window->FunctionEdit,True);
  279.  
  280.         Window->NumFramesEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  281.             GetScreenFont(),9,FRAMEEDITX,FRAMEEDITY,FRAMEEDITWIDTH,FRAMEEDITHEIGHT);
  282.         if (Window->NumFramesEdit == NIL)
  283.             {
  284.              FailurePoint7:
  285.                 goto FailurePoint6;
  286.             }
  287.         StringTemp = IntegerToString(WaveTableObjectEntriesPerTable(WaveTableObject));
  288.         if (StringTemp == NIL)
  289.             {
  290.              FailurePoint8:
  291.                 DisposeTextEdit(Window->NumFramesEdit);
  292.                 goto FailurePoint7;
  293.             }
  294.         TextEditNewRawData(Window->NumFramesEdit,StringTemp,"\x0a");
  295.         ReleasePtr(StringTemp);
  296.         TextEditHasBeenSaved(Window->NumFramesEdit);
  297.  
  298.         Window->NumTablesEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  299.             GetScreenFont(),9,TABLESEDITX,TABLESEDITY,TABLESEDITWIDTH,TABLESEDITHEIGHT);
  300.         if (Window->NumTablesEdit == NIL)
  301.             {
  302.              FailurePoint9:
  303.                 goto FailurePoint8;
  304.             }
  305.         StringTemp = IntegerToString(WaveTableObjectGetNumTables(WaveTableObject));
  306.         if (StringTemp == NIL)
  307.             {
  308.              FailurePoint10:
  309.                 DisposeTextEdit(Window->NumTablesEdit);
  310.                 goto FailurePoint9;
  311.             }
  312.         TextEditNewRawData(Window->NumTablesEdit,StringTemp,"\x0a");
  313.         ReleasePtr(StringTemp);
  314.         TextEditHasBeenSaved(Window->NumTablesEdit);
  315.  
  316.         Window->TestAttackDuration = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  317.             GetScreenFont(),9,TESTATTACKDURATIONX,TESTATTACKDURATIONY,TESTATTACKDURATIONWIDTH,
  318.             TESTATTACKDURATIONHEIGHT);
  319.         if (Window->TestAttackDuration == NIL)
  320.             {
  321.              FailurePoint11:
  322.                 goto FailurePoint10;
  323.             }
  324.         StringTemp = LongDoubleToString(WaveTableObjectGetTestAttack(WaveTableObject),
  325.             6,1e-4,1e6);
  326.         if (StringTemp == NIL)
  327.             {
  328.              FailurePoint12:
  329.                 DisposeTextEdit(Window->TestAttackDuration);
  330.                 goto FailurePoint11;
  331.             }
  332.         TextEditNewRawData(Window->TestAttackDuration,StringTemp,"\x0a");
  333.         ReleasePtr(StringTemp);
  334.  
  335.         Window->TestDecayDuration = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  336.             GetScreenFont(),9,TESTDECAYDURATIONX,TESTDECAYDURATIONY,TESTDECAYDURATIONWIDTH,
  337.             TESTDECAYDURATIONHEIGHT);
  338.         if (Window->TestDecayDuration == NIL)
  339.             {
  340.              FailurePoint13:
  341.                 goto FailurePoint12;
  342.             }
  343.         StringTemp = LongDoubleToString(WaveTableObjectGetTestDecay(WaveTableObject),
  344.             6,1e-4,1e6);
  345.         if (StringTemp == NIL)
  346.             {
  347.              FailurePoint14:
  348.                 DisposeTextEdit(Window->TestDecayDuration);
  349.                 goto FailurePoint13;
  350.             }
  351.         TextEditNewRawData(Window->TestDecayDuration,StringTemp,"\x0a");
  352.         ReleasePtr(StringTemp);
  353.  
  354.         Window->Bits8Button = NewIconButtonPreparedBitmaps(Window->ScreenID,BITS8BUTTONX,
  355.             BITS8BUTTONY,BITS8BUTTONWIDTH,BITS8BUTTONHEIGHT,Bits8Unselected,Bits8MouseDown,
  356.             Bits8Selected,Bits8Selected,eIconRadioMode);
  357.         if (Window->Bits8Button == NIL)
  358.             {
  359.              FailurePoint15:
  360.                 goto FailurePoint14;
  361.             }
  362.  
  363.         Window->Bits16Button = NewIconButtonPreparedBitmaps(Window->ScreenID,BITS16BUTTONX,
  364.             BITS16BUTTONY,BITS16BUTTONWIDTH,BITS16BUTTONHEIGHT,Bits16Unselected,
  365.             Bits16MouseDown,Bits16Selected,Bits16Selected,eIconRadioMode);
  366.         if (Window->Bits16Button == NIL)
  367.             {
  368.              FailurePoint16:
  369.                 DisposeIconButton(Window->Bits8Button);
  370.                 goto FailurePoint15;
  371.             }
  372.  
  373.         switch (WaveTableObjectGetNumBits(WaveTableObject))
  374.             {
  375.                 default:
  376.                     EXECUTE(PRERR(ForceAbort,"NewWaveTableWindow:  bad number of bits"));
  377.                     break;
  378.                 case eSample8bit:
  379.                     SetIconButtonState(Window->Bits8Button,True);
  380.                     break;
  381.                 case eSample16bit:
  382.                     SetIconButtonState(Window->Bits16Button,True);
  383.                     break;
  384.             }
  385.  
  386.         Window->TestButton = NewSimpleButton(Window->ScreenID,"Test",
  387.             TESTBUTTONX,TESTBUTTONY,TESTBUTTONWIDTH,TESTBUTTONHEIGHT);
  388.         if (Window->TestButton == NIL)
  389.             {
  390.              FailurePoint17:
  391.                 DisposeIconButton(Window->Bits16Button);
  392.                 goto FailurePoint16;
  393.             }
  394.  
  395.         Window->TableScroll = NewScrollBar(Window->ScreenID,eHScrollBar,
  396.             WAVEFORMVIEWX,TABLESCROLLY(WinHeight),WAVEFORMVIEWWIDTH(WinWidth));
  397.         if (Window->TableScroll == NIL)
  398.             {
  399.              FailurePoint18:
  400.                 DisposeSimpleButton(Window->TestButton);
  401.                 goto FailurePoint17;
  402.             }
  403.         Window->CurrentlyVisibleTable = 0;
  404.  
  405.         Window->WaveTableData = NewWaveTableStorDisp(WaveTableStorageNumBits(WaveData),
  406.             WaveTableStorageNumFramesPerTable(WaveData));
  407.         if (Window->WaveTableData == NIL)
  408.             {
  409.              FailurePoint19:
  410.                 DisposeScrollBar(Window->TableScroll);
  411.                 goto FailurePoint18;
  412.             }
  413.         Limit = WaveTableStorageNumTables(WaveData);
  414.         for (Scan = 0; Scan < Limit; Scan += 1)
  415.             {
  416.                 long                            Index;
  417.                 long                            IndexLimit;
  418.  
  419.                 if (!WaveTableStorDispAppendEntry(Window->WaveTableData))
  420.                     {
  421.                      FailurePoint20:
  422.                         DisposeWaveTableStorDisp(Window->WaveTableData);
  423.                         goto FailurePoint19;
  424.                     }
  425.                 IndexLimit = WaveTableStorageNumFramesPerTable(WaveData);
  426.                 for (Index = 0; Index < IndexLimit; Index += 1)
  427.                     {
  428.                         WaveTableStorDispSetFrame(Window->WaveTableData,Scan,Index,
  429.                             WaveTableStorageGetFrame(WaveData,Scan,Index));
  430.                     }
  431.             }
  432.  
  433.         Window->MyGenericWindow = CheckInNewWindow(Window->ScreenID,Window,
  434.             (void (*)(void*,MyBoolean,OrdType,OrdType,ModifierFlags))&WaveTableWindowDoIdle,
  435.             (void (*)(void*))&WaveTableWindowBecomeActive,
  436.             (void (*)(void*))&WaveTableWindowBecomeInactive,
  437.             (void (*)(void*))&WaveTableWindowJustResized,
  438.             (void (*)(OrdType,OrdType,ModifierFlags,void*))&WaveTableWindowDoMouseDown,
  439.             (void (*)(unsigned char,ModifierFlags,void*))&WaveTableWindowDoKeyDown,
  440.             (void (*)(void*))&WaveTableWindowClose,
  441.             (void (*)(void*))&WaveTableWindowMenuSetup,
  442.             (void (*)(void*,MenuItemType*))&WaveTableWindowDoMenuCommand);
  443.         if (Window->MyGenericWindow == NIL)
  444.             {
  445.              FailurePoint21:
  446.                 goto FailurePoint20;
  447.             }
  448.  
  449.         Window->TestFrequency = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  450.             GetScreenFont(),9,TESTFREQUENCYX,TESTFREQUENCYY,TESTFREQUENCYWIDTH,
  451.             TESTFREQUENCYHEIGHT);
  452.         if (Window->TestFrequency == NIL)
  453.             {
  454.              FailurePoint22:
  455.                 CheckOutDyingWindow(Window->MyGenericWindow);
  456.                 goto FailurePoint21;
  457.             }
  458.         StringTemp = LongDoubleToString(WaveTableObjectGetTestPitch(WaveTableObject),
  459.             13,1e-4,1e6);
  460.         if (StringTemp == NIL)
  461.             {
  462.              FailurePoint23:
  463.                 DisposeTextEdit(Window->TestFrequency);
  464.                 goto FailurePoint22;
  465.             }
  466.         TextEditNewRawData(Window->TestFrequency,StringTemp,"\x0a");
  467.         ReleasePtr(StringTemp);
  468.  
  469.         Window->TestSamplingRate = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  470.             GetScreenFont(),9,TESTSAMPLINGRATEX,TESTSAMPLINGRATEY,TESTSAMPLINGRATEWIDTH,
  471.             TESTSAMPLINGRATEHEIGHT);
  472.         if (Window->TestSamplingRate == NIL)
  473.             {
  474.              FailurePoint24:
  475.                 goto FailurePoint23;
  476.             }
  477.         StringTemp = IntegerToString(WaveTableObjectGetTestSamplingRate(WaveTableObject));
  478.         if (StringTemp == NIL)
  479.             {
  480.              FailurePoint25:
  481.                 DisposeTextEdit(Window->TestSamplingRate);
  482.                 goto FailurePoint24;
  483.             }
  484.         TextEditNewRawData(Window->TestSamplingRate,StringTemp,"\x0a");
  485.         ReleasePtr(StringTemp);
  486.  
  487.         Window->MyMenuItem = MakeNewMenuItem(mmWindowMenu,"x",0);
  488.         if (Window->MyMenuItem == NIL)
  489.             {
  490.              FailurePoint26:
  491.                 goto FailurePoint25;
  492.             }
  493.         if (!RegisterWindowMenuItem(Window->MyMenuItem,(void (*)(void*))&ActivateThisWindow,
  494.             Window->ScreenID))
  495.             {
  496.              FailurePoint27:
  497.                 KillMenuItem(Window->MyMenuItem);
  498.                 goto FailurePoint26;
  499.             }
  500.  
  501.         Window->WaveDataModified = False;
  502.         Window->ActiveTextEdit = Window->FunctionEdit;
  503.         Window->UndoBackupWaveTable = NIL;
  504.         WaveTableWindowResetTitlebar(Window);
  505.         WaveTableWindowUpdateScrollBar(Window);
  506.  
  507.         return Window;
  508.     }
  509.  
  510.  
  511. /* write back modified data and dispose of the wave table window */
  512. void                                DisposeWaveTableWindow(WaveTableWindowRec* Window)
  513.     {
  514.         CheckPtrExistence(Window);
  515.  
  516.         /* save data */
  517.         if (!WaveTableWindowWritebackModifiedData(Window))
  518.             {
  519.                 /* failed -- now what? */
  520.             }
  521.  
  522.         WaveTableObjectClosingWindowNotify(Window->WaveTableObject,
  523.             GetWindowXStart(Window->ScreenID),GetWindowYStart(Window->ScreenID),
  524.             GetWindowWidth(Window->ScreenID),GetWindowHeight(Window->ScreenID));
  525.         DeregisterWindowMenuItem(Window->MyMenuItem);
  526.         KillMenuItem(Window->MyMenuItem);
  527.         CheckOutDyingWindow(Window->MyGenericWindow);
  528.         DisposeWaveTableStorDisp(Window->WaveTableData);
  529.         if (Window->UndoBackupWaveTable != NIL)
  530.             {
  531.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  532.             }
  533.         DisposeScrollBar(Window->TableScroll);
  534.         DisposeIconButton(Window->Bits16Button);
  535.         DisposeIconButton(Window->Bits8Button);
  536.         DisposeTextEdit(Window->NameEdit);
  537.         DisposeTextEdit(Window->FunctionEdit);
  538.         DisposeTextEdit(Window->NumFramesEdit);
  539.         DisposeTextEdit(Window->NumTablesEdit);
  540.         DisposeTextEdit(Window->TestAttackDuration);
  541.         DisposeTextEdit(Window->TestDecayDuration);
  542.         DisposeTextEdit(Window->TestFrequency);
  543.         DisposeTextEdit(Window->TestSamplingRate);
  544.         DisposeSimpleButton(Window->TestButton);
  545.         KillWindow(Window->ScreenID);
  546.         ReleasePtr((char*)Window);
  547.     }
  548.  
  549.  
  550. /* return True if the data has been modified since the last time the file was saved */
  551. MyBoolean                        HasWaveTableWindowBeenModified(WaveTableWindowRec* Window)
  552.     {
  553.         CheckPtrExistence(Window);
  554.         return Window->WaveDataModified
  555.             || TextEditDoesItNeedToBeSaved(Window->NameEdit)
  556.             || TextEditDoesItNeedToBeSaved(Window->FunctionEdit)
  557.             || TextEditDoesItNeedToBeSaved(Window->TestAttackDuration)
  558.             || TextEditDoesItNeedToBeSaved(Window->TestDecayDuration)
  559.             || TextEditDoesItNeedToBeSaved(Window->TestFrequency)
  560.             || TextEditDoesItNeedToBeSaved(Window->TestSamplingRate);
  561.     }
  562.  
  563.  
  564. /* bring the window to the top and give it the focus */
  565. void                                WaveTableWindowBringToTop(WaveTableWindowRec* Window)
  566.     {
  567.         CheckPtrExistence(Window);
  568.         ActivateThisWindow(Window->ScreenID);
  569.     }
  570.  
  571.  
  572. void                                WaveTableWindowDoIdle(WaveTableWindowRec* Window,
  573.                                             MyBoolean CheckCursorFlag, OrdType XLoc, OrdType YLoc,
  574.                                             ModifierFlags Modifiers)
  575.     {
  576.         CheckPtrExistence(Window);
  577.         if (Window->ActiveTextEdit != NIL)
  578.             {
  579.                 TextEditUpdateCursor(Window->ActiveTextEdit);
  580.             }
  581.         if (CheckCursorFlag)
  582.             {
  583.                 if (TextEditIBeamTest(Window->NameEdit,XLoc,YLoc)
  584.                     || TextEditIBeamTest(Window->FunctionEdit,XLoc,YLoc)
  585.                     || TextEditIBeamTest(Window->NumFramesEdit,XLoc,YLoc)
  586.                     || TextEditIBeamTest(Window->NumTablesEdit,XLoc,YLoc)
  587.                     || TextEditIBeamTest(Window->TestAttackDuration,XLoc,YLoc)
  588.                     || TextEditIBeamTest(Window->TestDecayDuration,XLoc,YLoc)
  589.                     || TextEditIBeamTest(Window->TestFrequency,XLoc,YLoc)
  590.                     || TextEditIBeamTest(Window->TestSamplingRate,XLoc,YLoc))
  591.                     {
  592.                         SetIBeamCursor();
  593.                     }
  594.                 else if ((XLoc >= WAVEFORMVIEWX) && (YLoc >= WAVEFORMVIEWY)
  595.                     && (XLoc < WAVEFORMVIEWX + WAVEFORMVIEWWIDTH(GetWindowWidth(Window->ScreenID)))
  596.                     && (YLoc < WAVEFORMVIEWY
  597.                     + WAVEFORMVIEWHEIGHT(GetWindowHeight(Window->ScreenID)) - 15))
  598.                     {
  599.                         SetSampleInsertionCursor();
  600.                     }
  601.                 else
  602.                     {
  603.                         SetArrowCursor();
  604.                     }
  605.             }
  606.     }
  607.  
  608.  
  609. void                                WaveTableWindowBecomeActive(WaveTableWindowRec* Window)
  610.     {
  611.         OrdType                        XSize;
  612.         OrdType                        YSize;
  613.  
  614.         CheckPtrExistence(Window);
  615.         if (Window->ActiveTextEdit != NIL)
  616.             {
  617.                 EnableTextEditSelection(Window->ActiveTextEdit);
  618.             }
  619.         EnableScrollBar(Window->TableScroll);
  620.         XSize = GetWindowWidth(Window->ScreenID);
  621.         YSize = GetWindowHeight(Window->ScreenID);
  622.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  623.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(True/*enablegrowicon*/));
  624.     }
  625.  
  626.  
  627. void                                WaveTableWindowBecomeInactive(WaveTableWindowRec* Window)
  628.     {
  629.         OrdType                        XSize;
  630.         OrdType                        YSize;
  631.  
  632.         CheckPtrExistence(Window);
  633.         if (Window->ActiveTextEdit != NIL)
  634.             {
  635.                 DisableTextEditSelection(Window->ActiveTextEdit);
  636.             }
  637.         DisableScrollBar(Window->TableScroll);
  638.         XSize = GetWindowWidth(Window->ScreenID);
  639.         YSize = GetWindowHeight(Window->ScreenID);
  640.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  641.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(False/*disablegrowicon*/));
  642.     }
  643.  
  644.  
  645. void                                WaveTableWindowJustResized(WaveTableWindowRec* Window)
  646.     {
  647.         OrdType                        XSize;
  648.         OrdType                        YSize;
  649.  
  650.         CheckPtrExistence(Window);
  651.         XSize = GetWindowWidth(Window->ScreenID);
  652.         YSize = GetWindowHeight(Window->ScreenID);
  653.         SetClipRect(Window->ScreenID,0,0,XSize,YSize);
  654.         DrawBoxErase(Window->ScreenID,0,0,XSize,YSize);
  655.  
  656.         SetTextEditPosition(Window->FunctionEdit,EXPRESSIONEDITX,EXPRESSIONEDITY(YSize),
  657.             EXPRESSIONEDITWIDTH(XSize),EXPRESSIONEDITHEIGHT);
  658.         SetScrollLocation(Window->TableScroll,WAVEFORMVIEWX,TABLESCROLLY(YSize),
  659.             WAVEFORMVIEWWIDTH(XSize));
  660.     }
  661.  
  662.  
  663. static void                    WaveTableWindowScrollHook(long Parameter, ScrollType How,
  664.                                             WaveTableWindowRec* Window)
  665.     {
  666.         CheckPtrExistence(Window);
  667.         switch (How)
  668.             {
  669.                 case eScrollToPosition:
  670.                     Window->CurrentlyVisibleTable = Parameter;
  671.                     WaveTableWindowUpdateScrollBar(Window);
  672.                     WaveTableWindowRedrawTable(Window);
  673.                     break;
  674.                 case eScrollPageMinus:
  675.                     Window->CurrentlyVisibleTable -= PAGEINCREMENT;
  676.                     if (Window->CurrentlyVisibleTable < 0)
  677.                         {
  678.                             Window->CurrentlyVisibleTable = 0;
  679.                         }
  680.                     WaveTableWindowUpdateScrollBar(Window);
  681.                     WaveTableWindowRedrawTable(Window);
  682.                     break;
  683.                 case eScrollPagePlus:
  684.                     Window->CurrentlyVisibleTable += PAGEINCREMENT;
  685.                     if (Window->CurrentlyVisibleTable > WaveTableWindowGetNumTables(Window) - 1)
  686.                         {
  687.                             Window->CurrentlyVisibleTable = WaveTableWindowGetNumTables(Window) - 1;
  688.                         }
  689.                     if (Window->CurrentlyVisibleTable < 0)
  690.                         {
  691.                             /* just in case there are 0 tables -- this makes index become -1 */
  692.                             Window->CurrentlyVisibleTable = 0;
  693.                         }
  694.                     WaveTableWindowUpdateScrollBar(Window);
  695.                     WaveTableWindowRedrawTable(Window);
  696.                     break;
  697.                 case eScrollLineMinus:
  698.                     Window->CurrentlyVisibleTable -= 1;
  699.                     if (Window->CurrentlyVisibleTable < 0)
  700.                         {
  701.                             Window->CurrentlyVisibleTable = 0;
  702.                         }
  703.                     WaveTableWindowUpdateScrollBar(Window);
  704.                     WaveTableWindowRedrawTable(Window);
  705.                     break;
  706.                 case eScrollLinePlus:
  707.                     Window->CurrentlyVisibleTable += 1;
  708.                     if (Window->CurrentlyVisibleTable > WaveTableWindowGetNumTables(Window) - 1)
  709.                         {
  710.                             Window->CurrentlyVisibleTable = WaveTableWindowGetNumTables(Window) - 1;
  711.                         }
  712.                     if (Window->CurrentlyVisibleTable < 0)
  713.                         {
  714.                             /* just in case there are 0 tables -- this makes index become -1 */
  715.                             Window->CurrentlyVisibleTable = 0;
  716.                         }
  717.                     WaveTableWindowUpdateScrollBar(Window);
  718.                     WaveTableWindowRedrawTable(Window);
  719.                     break;
  720.                 default:
  721.                     EXECUTE(PRERR(AllowResume,"WaveTableWindowScrollHook:  Unknown scroll opcode"));
  722.                     break;
  723.             }
  724.     }
  725.  
  726.  
  727. #define SOUNDBUFFERLENGTHBYTES (16384)
  728. #define NUMSOUNDBUFFERS (4)
  729. static void                    WaveTablePlayIt(WaveTableWindowRec* Window)
  730.     {
  731.         long                                        NumTables;
  732.         long                                        Scan;
  733.         SoundOutputNumBits            SoundChannelBits;
  734.         largefixedsigned**            ReferenceArray;
  735.         unsigned long                        WaveformIndex;
  736.         unsigned long                        WaveformIncrementor;
  737.         unsigned long                        WaveformMask;
  738.         long                                        NumberOfIterationsAttack;
  739.         long                                        NumberOfIterationsDecay;
  740.         long                                        PlaybackSamplingRate;
  741.         void*                                        OutputBuffer;
  742.         long                                        OutputIndex;
  743.  
  744.         /* get the number of tables */
  745.         NumTables = WaveTableStorDispNumTables(Window->WaveTableData);
  746.  
  747.         /* fill in the buffer */
  748.         ReferenceArray = (largefixedsigned**)AllocPtrCanFail(sizeof(largefixedsigned*)
  749.             * NumTables,"WaveTablePlayIt:  ReferenceArray");
  750.         if (ReferenceArray == NIL)
  751.             {
  752.                 AlertHalt("There is not enough memory available to play the sample.",NIL);
  753.              FailurePoint1:
  754.                 return;
  755.             }
  756.         for (Scan = 0; Scan < WaveTableStorDispNumTables(Window->WaveTableData); Scan += 1)
  757.             {
  758.                 ReferenceArray[Scan] = WaveTableStorDispGetTable(Window->WaveTableData,Scan);
  759.             }
  760.  
  761.         /* how many bits should be used for playback */
  762.         switch (WaveTableStorDispNumBits(Window->WaveTableData))
  763.             {
  764.                 default:
  765.                     EXECUTE(PRERR(ForceAbort,"WaveTablePlayIt:  bad number of bits"));
  766.                     break;
  767.                 case eSample16bit:
  768.                     SoundChannelBits = e16bit;
  769.                     break;
  770.                 case eSample8bit:
  771.                     SoundChannelBits = e8bit;
  772.                     break;
  773.             }
  774.  
  775.         /* playback at what sampling rate */
  776.         PlaybackSamplingRate = WaveTableWindowGetTestSamplingRate(Window);
  777.         if (PlaybackSamplingRate < MINSAMPLINGRATE)
  778.             {
  779.                 PlaybackSamplingRate = MINSAMPLINGRATE;
  780.             }
  781.         if (PlaybackSamplingRate > MAXSAMPLINGRATE)
  782.             {
  783.                 PlaybackSamplingRate = MAXSAMPLINGRATE;
  784.             }
  785.  
  786.         /* this is the initial index into the wave table */
  787.         WaveformIndex = 0;
  788.  
  789.         /* this is the 16.16 bit fixed point number used to increment the index */
  790.         /* into the wave table */
  791.         WaveformIncrementor = WaveTableWindowGetNumFramesPerTable(Window)
  792.             * WaveTableWindowGetPitch(Window) / PlaybackSamplingRate * 65536;
  793.  
  794.         /* this is used to mask off all garbage bits from the index when */
  795.         /* looking values up in the wave table */
  796.         WaveformMask = WaveTableWindowGetNumFramesPerTable(Window) - 1;
  797.  
  798.         /* the number of times each wave slice has to be used */
  799.         NumberOfIterationsAttack = WaveTableWindowGetAscendingDuration(Window)
  800.             / (double)NumTables * PlaybackSamplingRate;
  801.         NumberOfIterationsDecay = WaveTableWindowGetDescendingDuration(Window)
  802.             / (double)NumTables * PlaybackSamplingRate;
  803.  
  804.         if (!OpenSoundChannel(PlaybackSamplingRate,eMono,SoundChannelBits,
  805.             SOUNDBUFFERLENGTHBYTES,NUMSOUNDBUFFERS,NUMSOUNDBUFFERS))
  806.             {
  807.                 AlertHalt("Unable top open the sound device.",NIL);
  808.              FailurePoint2:
  809.                 ReleasePtr((char*)ReferenceArray);
  810.                 goto FailurePoint1;
  811.             }
  812.         OutputIndex = 0;
  813.         do
  814.             {
  815.                 OutputBuffer = CheckOutSoundBuffer();
  816.             } while (OutputBuffer == NIL);
  817.  
  818.         if (SoundChannelBits == e16bit)
  819.             {
  820.                 for (Scan = 0; Scan < NumTables; Scan += 1)
  821.                     {
  822.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  823.                         long                                    Index;
  824.  
  825.                         for (Index = 0; Index < NumberOfIterationsAttack; Index += 1)
  826.                             {
  827.                                 unsigned long                    SampleReference;
  828.                                 signed short                    Left;
  829.                                 signed short                    Right;
  830.                                 signed long                        Fraction;
  831.  
  832.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  833.                                 Left = Buffer[SampleReference] >> SIXTEENBITSHIFTFACTOR;
  834.                                 Right = Buffer[SampleReference + 1] >> SIXTEENBITSHIFTFACTOR;
  835.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  836.                                 WaveformIndex += WaveformIncrementor;
  837.                                 ((short*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  838.                                     + Right * Fraction) >> 15;
  839.                                 OutputIndex += 1;
  840.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(short))
  841.                                     {
  842.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(short),
  843.                                             NIL,NIL);
  844.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  845.                                             {
  846.                                                 goto EscapePoint;
  847.                                             }
  848.                                         do
  849.                                             {
  850.                                                 OutputBuffer = CheckOutSoundBuffer();
  851.                                             } while (OutputBuffer == NIL);
  852.                                         OutputIndex = 0;
  853.                                     }
  854.                             }
  855.                     }
  856.             }
  857.          else
  858.             {
  859.                 for (Scan = 0; Scan < NumTables; Scan += 1)
  860.                     {
  861.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  862.                         long                                    Index;
  863.  
  864.                         for (Index = 0; Index < NumberOfIterationsAttack; Index += 1)
  865.                             {
  866.                                 unsigned long                    SampleReference;
  867.                                 signed short                    Left;
  868.                                 signed short                    Right;
  869.                                 signed long                        Fraction;
  870.  
  871.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  872.                                 Left = Buffer[SampleReference] >> EIGHTBITSHIFTFACTOR;
  873.                                 Right = Buffer[SampleReference + 1] >> EIGHTBITSHIFTFACTOR;
  874.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  875.                                 WaveformIndex += WaveformIncrementor;
  876.                                 ((char*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  877.                                     + Right * Fraction) >> 15;
  878.                                 OutputIndex += 1;
  879.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(char))
  880.                                     {
  881.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(char),
  882.                                             NIL,NIL);
  883.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  884.                                             {
  885.                                                 goto EscapePoint;
  886.                                             }
  887.                                         do
  888.                                             {
  889.                                                 OutputBuffer = CheckOutSoundBuffer();
  890.                                             } while (OutputBuffer == NIL);
  891.                                         OutputIndex = 0;
  892.                                     }
  893.                             }
  894.                     }
  895.             }
  896.  
  897.         if (SoundChannelBits == e16bit)
  898.             {
  899.                 for (Scan = NumTables - 1; Scan >= 0; Scan -= 1)
  900.                     {
  901.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  902.                         long                                    Index;
  903.  
  904.                         for (Index = 0; Index < NumberOfIterationsDecay; Index += 1)
  905.                             {
  906.                                 unsigned long                    SampleReference;
  907.                                 signed short                    Left;
  908.                                 signed short                    Right;
  909.                                 signed long                        Fraction;
  910.  
  911.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  912.                                 Left = Buffer[SampleReference] >> SIXTEENBITSHIFTFACTOR;
  913.                                 Right = Buffer[SampleReference + 1] >> SIXTEENBITSHIFTFACTOR;
  914.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  915.                                 WaveformIndex += WaveformIncrementor;
  916.                                 ((short*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  917.                                     + Right * Fraction) >> 15;
  918.                                 OutputIndex += 1;
  919.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(short))
  920.                                     {
  921.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(short),
  922.                                             NIL,NIL);
  923.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  924.                                             {
  925.                                                 goto EscapePoint;
  926.                                             }
  927.                                         do
  928.                                             {
  929.                                                 OutputBuffer = CheckOutSoundBuffer();
  930.                                             } while (OutputBuffer == NIL);
  931.                                         OutputIndex = 0;
  932.                                     }
  933.                             }
  934.                     }
  935.                 SubmitBuffer(OutputBuffer,OutputIndex / sizeof(short),NIL,NIL);
  936.             }
  937.          else
  938.             {
  939.                 for (Scan = NumTables - 1; Scan >= 0; Scan -= 1)
  940.                     {
  941.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  942.                         long                                    Index;
  943.  
  944.                         for (Index = 0; Index < NumberOfIterationsDecay; Index += 1)
  945.                             {
  946.                                 unsigned long                    SampleReference;
  947.                                 signed short                    Left;
  948.                                 signed short                    Right;
  949.                                 signed long                        Fraction;
  950.  
  951.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  952.                                 Left = Buffer[SampleReference] >> EIGHTBITSHIFTFACTOR;
  953.                                 Right = Buffer[SampleReference + 1] >> EIGHTBITSHIFTFACTOR;
  954.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  955.                                 WaveformIndex += WaveformIncrementor;
  956.                                 ((char*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  957.                                     + Right * Fraction) >> 15;
  958.                                 OutputIndex += 1;
  959.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(char))
  960.                                     {
  961.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(char),
  962.                                             NIL,NIL);
  963.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  964.                                             {
  965.                                                 goto EscapePoint;
  966.                                             }
  967.                                         do
  968.                                             {
  969.                                                 OutputBuffer = CheckOutSoundBuffer();
  970.                                             } while (OutputBuffer == NIL);
  971.                                         OutputIndex = 0;
  972.                                     }
  973.                             }
  974.                     }
  975.                 SubmitBuffer(OutputBuffer,OutputIndex / sizeof(char),NIL,NIL);
  976.             }
  977.  
  978.      EscapePoint:
  979.         CloseSoundChannel(NIL,NIL);
  980.         ReleasePtr((char*)ReferenceArray);
  981.     }
  982.  
  983.  
  984. void                                WaveTableWindowDoMouseDown(OrdType XLoc, OrdType YLoc,
  985.                                             ModifierFlags Modifiers, WaveTableWindowRec* Window)
  986.     {
  987.         CheckPtrExistence(Window);
  988.         if ((XLoc >= GetWindowWidth(Window->ScreenID) - 15)
  989.             && (XLoc < GetWindowWidth(Window->ScreenID))
  990.             && (YLoc >= GetWindowHeight(Window->ScreenID) - 15)
  991.             && (YLoc < GetWindowHeight(Window->ScreenID)))
  992.             {
  993.                 UserGrowWindow(Window->ScreenID,XLoc,YLoc);
  994.                 WaveTableWindowJustResized(Window);
  995.             }
  996.         else if (TextEditHitTest(Window->NameEdit,XLoc,YLoc))
  997.             {
  998.                 if (Window->ActiveTextEdit != Window->NameEdit)
  999.                     {
  1000.                         if (Window->ActiveTextEdit != NIL)
  1001.                             {
  1002.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1003.                             }
  1004.                         Window->ActiveTextEdit = Window->NameEdit;
  1005.                         EnableTextEditSelection(Window->NameEdit);
  1006.                     }
  1007.                 TextEditDoMouseDown(Window->NameEdit,XLoc,YLoc,Modifiers);
  1008.             }
  1009.         else if (TextEditHitTest(Window->FunctionEdit,XLoc,YLoc))
  1010.             {
  1011.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1012.                     {
  1013.                         if (Window->ActiveTextEdit != NIL)
  1014.                             {
  1015.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1016.                             }
  1017.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1018.                         EnableTextEditSelection(Window->FunctionEdit);
  1019.                     }
  1020.                 TextEditDoMouseDown(Window->FunctionEdit,XLoc,YLoc,Modifiers);
  1021.             }
  1022.         else if (TextEditHitTest(Window->TestAttackDuration,XLoc,YLoc))
  1023.             {
  1024.                 if (Window->ActiveTextEdit != Window->TestAttackDuration)
  1025.                     {
  1026.                         if (Window->ActiveTextEdit != NIL)
  1027.                             {
  1028.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1029.                             }
  1030.                         Window->ActiveTextEdit = Window->TestAttackDuration;
  1031.                         EnableTextEditSelection(Window->TestAttackDuration);
  1032.                     }
  1033.                 TextEditDoMouseDown(Window->TestAttackDuration,XLoc,YLoc,Modifiers);
  1034.             }
  1035.         else if (TextEditHitTest(Window->TestDecayDuration,XLoc,YLoc))
  1036.             {
  1037.                 if (Window->ActiveTextEdit != Window->TestDecayDuration)
  1038.                     {
  1039.                         if (Window->ActiveTextEdit != NIL)
  1040.                             {
  1041.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1042.                             }
  1043.                         Window->ActiveTextEdit = Window->TestDecayDuration;
  1044.                         EnableTextEditSelection(Window->TestDecayDuration);
  1045.                     }
  1046.                 TextEditDoMouseDown(Window->TestDecayDuration,XLoc,YLoc,Modifiers);
  1047.             }
  1048.         else if (TextEditHitTest(Window->TestFrequency,XLoc,YLoc))
  1049.             {
  1050.                 if (Window->ActiveTextEdit != Window->TestFrequency)
  1051.                     {
  1052.                         if (Window->ActiveTextEdit != NIL)
  1053.                             {
  1054.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1055.                             }
  1056.                         Window->ActiveTextEdit = Window->TestFrequency;
  1057.                         EnableTextEditSelection(Window->TestFrequency);
  1058.                     }
  1059.                 TextEditDoMouseDown(Window->TestFrequency,XLoc,YLoc,Modifiers);
  1060.             }
  1061.         else if (TextEditHitTest(Window->TestSamplingRate,XLoc,YLoc))
  1062.             {
  1063.                 if (Window->ActiveTextEdit != Window->TestSamplingRate)
  1064.                     {
  1065.                         if (Window->ActiveTextEdit != NIL)
  1066.                             {
  1067.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1068.                             }
  1069.                         Window->ActiveTextEdit = Window->TestSamplingRate;
  1070.                         EnableTextEditSelection(Window->TestSamplingRate);
  1071.                     }
  1072.                 TextEditDoMouseDown(Window->TestSamplingRate,XLoc,YLoc,Modifiers);
  1073.             }
  1074.         else if (TextEditHitTest(Window->NumFramesEdit,XLoc,YLoc))
  1075.             {
  1076.                 WaveTableWindowSetNewNumFrames(Window);
  1077.             }
  1078.         else if (TextEditHitTest(Window->NumTablesEdit,XLoc,YLoc))
  1079.             {
  1080.                 WaveTableWindowSetNewNumTables(Window);
  1081.             }
  1082.         else if (IconButtonHitTest(Window->Bits8Button,XLoc,YLoc))
  1083.             {
  1084.                 if (IconButtonMouseDown(Window->Bits8Button,XLoc,YLoc,NIL,NIL))
  1085.                     {
  1086.                         SetWaveTableStorDispNumBits(Window->WaveTableData,eSample8bit);
  1087.                         SetIconButtonState(Window->Bits16Button,False);
  1088.                         Window->WaveDataModified = True;
  1089.                     }
  1090.             }
  1091.         else if (IconButtonHitTest(Window->Bits16Button,XLoc,YLoc))
  1092.             {
  1093.                 if (IconButtonMouseDown(Window->Bits16Button,XLoc,YLoc,NIL,NIL))
  1094.                     {
  1095.                         SetWaveTableStorDispNumBits(Window->WaveTableData,eSample16bit);
  1096.                         SetIconButtonState(Window->Bits8Button,False);
  1097.                         Window->WaveDataModified = True;
  1098.                     }
  1099.             }
  1100.         else if (ScrollHitTest(Window->TableScroll,XLoc,YLoc))
  1101.             {
  1102.                 ScrollHitProc(Window->TableScroll,CheckModifiers(),XLoc,YLoc,Window,
  1103.                     (void (*)(long,ScrollType,void*))&WaveTableWindowScrollHook);
  1104.             }
  1105.         else if (SimpleButtonHitTest(Window->TestButton,XLoc,YLoc))
  1106.             {
  1107.                 if (SimpleButtonMouseDown(Window->TestButton,XLoc,YLoc,NIL,NIL))
  1108.                     {
  1109.                         WaveTablePlayIt(Window);
  1110.                     }
  1111.             }
  1112.         else
  1113.             {
  1114.                 if (Window->ActiveTextEdit != NIL)
  1115.                     {
  1116.                         DisableTextEditSelection(Window->ActiveTextEdit);
  1117.                         Window->ActiveTextEdit = NIL;
  1118.                     }
  1119.             }
  1120.     }
  1121.  
  1122.  
  1123. void                                WaveTableWindowDoKeyDown(unsigned char KeyCode,
  1124.                                             ModifierFlags Modifiers, WaveTableWindowRec* Window)
  1125.     {
  1126.         CheckPtrExistence(Window);
  1127.         if (Window->ActiveTextEdit != NIL)
  1128.             {
  1129.                 TextEditDoKeyPressed(Window->ActiveTextEdit,KeyCode,Modifiers);
  1130.             }
  1131.     }
  1132.  
  1133.  
  1134. void                                WaveTableWindowClose(WaveTableWindowRec* Window)
  1135.     {
  1136.         CheckPtrExistence(Window);
  1137.         DisposeWaveTableWindow(Window);
  1138.     }
  1139.  
  1140.  
  1141. void                                WaveTableWindowUpdator(WaveTableWindowRec* Window)
  1142.     {
  1143.         OrdType                        Height;
  1144.         OrdType                        Width;
  1145.  
  1146.         CheckPtrExistence(Window);
  1147.         Width = GetWindowWidth(Window->ScreenID);
  1148.         Height = GetWindowHeight(Window->ScreenID);
  1149.  
  1150.         TextEditFullRedraw(Window->NameEdit);
  1151.         TextEditFullRedraw(Window->FunctionEdit);
  1152.         TextEditFullRedraw(Window->NumFramesEdit);
  1153.         TextEditFullRedraw(Window->NumTablesEdit);
  1154.         TextEditFullRedraw(Window->TestAttackDuration);
  1155.         TextEditFullRedraw(Window->TestDecayDuration);
  1156.         TextEditFullRedraw(Window->TestFrequency);
  1157.         TextEditFullRedraw(Window->TestSamplingRate);
  1158.         RedrawSimpleButton(Window->TestButton);
  1159.         RedrawIconButton(Window->Bits8Button);
  1160.         RedrawIconButton(Window->Bits16Button);
  1161.         RedrawScrollBar(Window->TableScroll);
  1162.         WaveTableWindowRedrawTable(Window);
  1163.  
  1164.         SetClipRect(Window->ScreenID,0,0,Width,Height);
  1165.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Name:",5,NAMEX,NAMEY,ePlain);
  1166.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Frames:",7,FRAMEX,FRAMEY,ePlain);
  1167.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Tables:",7,TABLESX,TABLESY,ePlain);
  1168.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Attack:",12,
  1169.             TESTATTACKX,TESTATTACKY,ePlain);
  1170.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Decay:",11,
  1171.             TESTDECAYX,TESTDECAYY,ePlain);
  1172.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Freq:",10,
  1173.             TESTFREQX,TESTFREQY,ePlain);
  1174.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Smpl Rate:",15,
  1175.             TESTSAMPLX,TESTSAMPLY,ePlain);
  1176.  
  1177.         SetClipRect(Window->ScreenID,Width - 15,Height - 15,Width,Height);
  1178.         DrawBitmap(Window->ScreenID,Width - 15,Height - 15,
  1179.             GetGrowIcon(Window->MyGenericWindow == GetCurrentWindowID()));
  1180.     }
  1181.  
  1182.  
  1183. void                                WaveTableWindowMenuSetup(WaveTableWindowRec* Window)
  1184.     {
  1185.         CheckPtrExistence(Window);
  1186.         MainWindowEnableGlobalMenus(Window->MainWindow);
  1187.         EnableMenuItem(mPaste);
  1188.         ChangeItemName(mPaste,"Paste Text");
  1189.         if (Window->ActiveTextEdit != NIL)
  1190.             {
  1191.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1192.                     {
  1193.                         EnableMenuItem(mCut);
  1194.                         ChangeItemName(mCut,"Cut Text");
  1195.                         EnableMenuItem(mCopy);
  1196.                         ChangeItemName(mCopy,"Copy Text");
  1197.                         EnableMenuItem(mClear);
  1198.                         ChangeItemName(mClear,"Clear Text");
  1199.                     }
  1200.                 EnableMenuItem(mSelectAll);
  1201.                 ChangeItemName(mSelectAll,"Select All Text");
  1202.                 if (TextEditCanWeUndo(Window->ActiveTextEdit))
  1203.                     {
  1204.                         EnableMenuItem(mUndo);
  1205.                         ChangeItemName(mUndo,"Undo Text Change");
  1206.                     }
  1207.             }
  1208.          else
  1209.             {
  1210.                 if (Window->UndoBackupWaveTable != NIL)
  1211.                     {
  1212.                         EnableMenuItem(mUndo);
  1213.                         ChangeItemName(mUndo,"Undo Wave Table Edit");
  1214.                     }
  1215.             }
  1216.         EnableMenuItem(mCloseFile);
  1217.         ChangeItemName(mCloseFile,"Close Wave Table Editor");
  1218.         EnableMenuItem(mEvaluateCalc);
  1219.         EnableMenuItem(mShiftLeft);
  1220.         EnableMenuItem(mShiftRight);
  1221.         EnableMenuItem(mBalanceParens);
  1222.         ChangeItemName(mDeleteObject,"Delete Wave Table");
  1223.         EnableMenuItem(mDeleteObject);
  1224.         EnableMenuItem(mFind);
  1225.         if (PtrSize(GlobalSearchString) != 0)
  1226.             {
  1227.                 EnableMenuItem(mFindAgain);
  1228.                 if ((Window->ActiveTextEdit != NIL)
  1229.                     && TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1230.                     {
  1231.                         EnableMenuItem(mReplace);
  1232.                         EnableMenuItem(mReplaceAndFindAgain);
  1233.                     }
  1234.             }
  1235.         if ((Window->ActiveTextEdit != NIL)
  1236.             && TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1237.             {
  1238.                 EnableMenuItem(mEnterSelection);
  1239.             }
  1240.         SetItemCheckmark(Window->MyMenuItem);
  1241.     }
  1242.  
  1243.  
  1244. void                                WaveTableWindowDoMenuCommand(WaveTableWindowRec* Window,
  1245.                                             MenuItemType* MenuItem)
  1246.     {
  1247.         CheckPtrExistence(Window);
  1248.         if (MainWindowDoGlobalMenuItem(Window->MainWindow,MenuItem))
  1249.             {
  1250.             }
  1251.         else if (MenuItem == mPaste)
  1252.             {
  1253.                 if (Window->ActiveTextEdit != NIL)
  1254.                     {
  1255.                         TextEditDoMenuPaste(Window->ActiveTextEdit);
  1256.                     }
  1257.             }
  1258.         else if (MenuItem == mCut)
  1259.             {
  1260.                 if (Window->ActiveTextEdit != NIL)
  1261.                     {
  1262.                         TextEditDoMenuCut(Window->ActiveTextEdit);
  1263.                     }
  1264.             }
  1265.         else if (MenuItem == mCopy)
  1266.             {
  1267.                 if (Window->ActiveTextEdit != NIL)
  1268.                     {
  1269.                         TextEditDoMenuCopy(Window->ActiveTextEdit);
  1270.                     }
  1271.             }
  1272.         else if (MenuItem == mClear)
  1273.             {
  1274.                 if (Window->ActiveTextEdit != NIL)
  1275.                     {
  1276.                         TextEditDoMenuClear(Window->ActiveTextEdit);
  1277.                     }
  1278.             }
  1279.         else if (MenuItem == mSelectAll)
  1280.             {
  1281.                 if (Window->ActiveTextEdit != NIL)
  1282.                     {
  1283.                         TextEditDoMenuSelectAll(Window->ActiveTextEdit);
  1284.                     }
  1285.             }
  1286.         else if (MenuItem == mUndo)
  1287.             {
  1288.                 if (Window->ActiveTextEdit != NIL)
  1289.                     {
  1290.                         TextEditDoMenuUndo(Window->ActiveTextEdit);
  1291.                     }
  1292.                  else
  1293.                     {
  1294.                         WaveTableStorDispRec*        Temp;
  1295.  
  1296.                         Temp = Window->UndoBackupWaveTable;
  1297.                         Window->UndoBackupWaveTable = Window->WaveTableData;
  1298.                         Window->WaveTableData = Temp;
  1299.                         Window->WaveDataModified = True;
  1300.                         WaveTableWindowUpdateAllParameters(Window);
  1301.                     }
  1302.             }
  1303.         else if (MenuItem == mCloseFile)
  1304.             {
  1305.                 WaveTableWindowClose(Window);
  1306.             }
  1307.         else if (MenuItem == mEvaluateCalc)
  1308.             {
  1309.                 WaveTableWindowEvaluateFunction(Window);
  1310.             }
  1311.         else if (MenuItem == mShiftLeft)
  1312.             {
  1313.                 TextEditShiftSelectionLeftOneTab(Window->ActiveTextEdit);
  1314.             }
  1315.         else if (MenuItem == mShiftRight)
  1316.             {
  1317.                 TextEditShiftSelectionRightOneTab(Window->ActiveTextEdit);
  1318.             }
  1319.         else if (MenuItem == mBalanceParens)
  1320.             {
  1321.                 TextEditBalanceParens(Window->ActiveTextEdit);
  1322.             }
  1323.         else if (MenuItem == mDeleteObject)
  1324.             {
  1325.                 WaveTableListDeleteWaveTable(Window->WaveTableList,Window->WaveTableObject);
  1326.             }
  1327.         else if (MenuItem == mFind)
  1328.             {
  1329.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1330.                     {
  1331.                         if (Window->ActiveTextEdit != NIL)
  1332.                             {
  1333.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1334.                             }
  1335.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1336.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1337.                     }
  1338.                 switch (DoFindDialog(&GlobalSearchString,&GlobalReplaceString,
  1339.                     mCut,mPaste,mCopy,mUndo,mSelectAll,mClear))
  1340.                     {
  1341.                         default:
  1342.                             EXECUTE(PRERR(ForceAbort,
  1343.                                 "WaveTableWindowDoMenuCommand:  bad value from DoFindDialog"));
  1344.                             break;
  1345.                         case eFindCancel:
  1346.                         case eDontFind:
  1347.                             break;
  1348.                         case eFindFromStart:
  1349.                             SetTextEditInsertionPoint(Window->ActiveTextEdit,0,0);
  1350.                             TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1351.                             TextEditShowSelection(Window->ActiveTextEdit);
  1352.                             break;
  1353.                         case eFindAgain:
  1354.                             TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1355.                             TextEditShowSelection(Window->ActiveTextEdit);
  1356.                             break;
  1357.                     }
  1358.             }
  1359.         else if (MenuItem == mFindAgain)
  1360.             {
  1361.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1362.                     {
  1363.                         if (Window->ActiveTextEdit != NIL)
  1364.                             {
  1365.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1366.                             }
  1367.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1368.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1369.                     }
  1370.                 TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1371.                 TextEditShowSelection(Window->ActiveTextEdit);
  1372.             }
  1373.         else if (MenuItem == mReplace)
  1374.             {
  1375.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1376.                     {
  1377.                         if (Window->ActiveTextEdit != NIL)
  1378.                             {
  1379.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1380.                             }
  1381.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1382.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1383.                     }
  1384.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1385.                     {
  1386.                         TextEditInsertRawData(Window->ActiveTextEdit,GlobalReplaceString,
  1387.                             SYSTEMLINEFEED);
  1388.                     }
  1389.             }
  1390.         else if (MenuItem == mReplaceAndFindAgain)
  1391.             {
  1392.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1393.                     {
  1394.                         if (Window->ActiveTextEdit != NIL)
  1395.                             {
  1396.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1397.                             }
  1398.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1399.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1400.                     }
  1401.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1402.                     {
  1403.                         TextEditInsertRawData(Window->ActiveTextEdit,GlobalReplaceString,
  1404.                             SYSTEMLINEFEED);
  1405.                         TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1406.                         TextEditShowSelection(Window->ActiveTextEdit);
  1407.                     }
  1408.             }
  1409.         else if (MenuItem == mEnterSelection)
  1410.             {
  1411.                 if (Window->ActiveTextEdit != NIL)
  1412.                     {
  1413.                         char*                        NewString;
  1414.  
  1415.                         NewString = TextEditGetSelection(Window->ActiveTextEdit);
  1416.                         if (NewString != NIL)
  1417.                             {
  1418.                                 ReleasePtr(GlobalSearchString);
  1419.                                 GlobalSearchString = NewString;
  1420.                             }
  1421.                     }
  1422.             }
  1423.         else
  1424.             {
  1425.                 EXECUTE(PRERR(AllowResume,"WaveTableWindowDoMenuCommand:  unknown menu command"));
  1426.             }
  1427.     }
  1428.  
  1429.  
  1430. /* get a copy of the wave table's name */
  1431. char*                                WaveTableWindowGetNameCopy(WaveTableWindowRec* Window)
  1432.     {
  1433.         char*                            TextCopy;
  1434.  
  1435.         CheckPtrExistence(Window);
  1436.         TextCopy = TextEditGetRawData(Window->NameEdit,"\x0a");
  1437.         if (TextCopy != NIL)
  1438.             {
  1439.                 SetTag(TextCopy,"WaveTableWindowNameCopy");
  1440.             }
  1441.         return TextCopy;
  1442.     }
  1443.  
  1444.  
  1445. /* get a copy of the wave table's formula */
  1446. char*                                WaveTableWindowGetFormulaCopy(WaveTableWindowRec* Window)
  1447.     {
  1448.         char*                            TextCopy;
  1449.  
  1450.         CheckPtrExistence(Window);
  1451.         TextCopy = TextEditGetRawData(Window->FunctionEdit,"\x0a");
  1452.         if (TextCopy != NIL)
  1453.             {
  1454.                 SetTag(TextCopy,"WaveTableWindowFormulaCopy");
  1455.             }
  1456.         return TextCopy;
  1457.     }
  1458.  
  1459.  
  1460. /* get the number of bits used for the wave table */
  1461. NumBitsType                    WaveTableWindowGetNumBits(WaveTableWindowRec* Window)
  1462.     {
  1463.         CheckPtrExistence(Window);
  1464.         if (GetIconButtonState(Window->Bits16Button))
  1465.             {
  1466.                 return eSample16bit;
  1467.             }
  1468.          else
  1469.             {
  1470.                 return eSample8bit;
  1471.             }
  1472.     }
  1473.  
  1474.  
  1475. /* get the number of periods in the wave table */
  1476. long                                WaveTableWindowGetNumTables(WaveTableWindowRec* Window)
  1477.     {
  1478.         CheckPtrExistence(Window);
  1479.         return WaveTableStorDispNumTables(Window->WaveTableData);
  1480.     }
  1481.  
  1482.  
  1483. /* get the number of frames in each period of the wave table */
  1484. long                                WaveTableWindowGetNumFramesPerTable(WaveTableWindowRec* Window)
  1485.     {
  1486.         CheckPtrExistence(Window);
  1487.         return WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  1488.     }
  1489.  
  1490.  
  1491. /* get the pitch at which the wave table should be tested */
  1492. double                            WaveTableWindowGetPitch(WaveTableWindowRec* Window)
  1493.     {
  1494.         char*                            Text;
  1495.         double                        ReturnValue;
  1496.  
  1497.         CheckPtrExistence(Window);
  1498.         Text = TextEditGetRawData(Window->TestFrequency,SYSTEMLINEFEED);
  1499.         if (Text != NIL)
  1500.             {
  1501.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1502.                 ReleasePtr(Text);
  1503.             }
  1504.          else
  1505.             {
  1506.                 ReturnValue = 261.625565300598635;
  1507.             }
  1508.         return ReturnValue;
  1509.     }
  1510.  
  1511.  
  1512. /* get the duration (seconds) for the increasing table index phase of the test */
  1513. double                            WaveTableWindowGetAscendingDuration(WaveTableWindowRec* Window)
  1514.     {
  1515.         char*                            Text;
  1516.         double                        ReturnValue;
  1517.  
  1518.         CheckPtrExistence(Window);
  1519.         Text = TextEditGetRawData(Window->TestAttackDuration,SYSTEMLINEFEED);
  1520.         if (Text != NIL)
  1521.             {
  1522.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1523.                 ReleasePtr(Text);
  1524.             }
  1525.          else
  1526.             {
  1527.                 ReturnValue = 1;
  1528.             }
  1529.         return ReturnValue;
  1530.     }
  1531.  
  1532.  
  1533. /* get the duration (seconds) for the decreasing table index phase of the test */
  1534. double                            WaveTableWindowGetDescendingDuration(WaveTableWindowRec* Window)
  1535.     {
  1536.         char*                            Text;
  1537.         double                        ReturnValue;
  1538.  
  1539.         CheckPtrExistence(Window);
  1540.         Text = TextEditGetRawData(Window->TestDecayDuration,SYSTEMLINEFEED);
  1541.         if (Text != NIL)
  1542.             {
  1543.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1544.                 ReleasePtr(Text);
  1545.             }
  1546.          else
  1547.             {
  1548.                 ReturnValue = 2;
  1549.             }
  1550.         return ReturnValue;
  1551.     }
  1552.  
  1553.  
  1554. /* get the sampling rate to use for the test */
  1555. long                                WaveTableWindowGetTestSamplingRate(WaveTableWindowRec* Window)
  1556.     {
  1557.         char*                            Text;
  1558.         double                        ReturnValue;
  1559.  
  1560.         CheckPtrExistence(Window);
  1561.         Text = TextEditGetRawData(Window->TestSamplingRate,SYSTEMLINEFEED);
  1562.         if (Text != NIL)
  1563.             {
  1564.                 ReturnValue = StringToInteger(Text,PtrSize(Text));
  1565.                 ReleasePtr(Text);
  1566.             }
  1567.          else
  1568.             {
  1569.                 ReturnValue = 22050;
  1570.             }
  1571.         return ReturnValue;
  1572.     }
  1573.  
  1574.  
  1575. /* reset the scroll bar indices and redraw it */
  1576. void                                WaveTableWindowUpdateScrollBar(WaveTableWindowRec* Window)
  1577.     {
  1578.         CheckPtrExistence(Window);
  1579.         SetMaxScrollIndex(Window->TableScroll,WaveTableWindowGetNumTables(Window));
  1580.         SetScrollIndex(Window->TableScroll,Window->CurrentlyVisibleTable);
  1581.     }
  1582.  
  1583.  
  1584. /* redraw the wave table waveform box */
  1585. void                                WaveTableWindowRedrawTable(WaveTableWindowRec* Window)
  1586.     {
  1587.         OrdType                        WindowWidth;
  1588.         OrdType                        WindowHeight;
  1589.         long                            Scan;
  1590.         long                            Limit;
  1591.         OrdType                        PreviousYValue;
  1592.         OrdType                        PreviousXValue;
  1593.         MyBoolean                    PreviousYValueIsValid;
  1594.  
  1595.         CheckPtrExistence(Window);
  1596.         WindowWidth = GetWindowWidth(Window->ScreenID);
  1597.         WindowHeight = GetWindowHeight(Window->ScreenID);
  1598.         SetClipRect(Window->ScreenID,WAVEFORMVIEWX,WAVEFORMVIEWY,
  1599.             WAVEFORMVIEWWIDTH(WindowWidth),WAVEFORMVIEWHEIGHT(WindowHeight));
  1600.         DrawBoxFrame(Window->ScreenID,eBlack,WAVEFORMVIEWX,WAVEFORMVIEWY,
  1601.             WAVEFORMVIEWWIDTH(WindowWidth),WAVEFORMVIEWHEIGHT(WindowHeight));
  1602.         if (WaveTableWindowGetNumTables(Window) == 0)
  1603.             {
  1604.                 DrawBoxPaint(Window->ScreenID,eLightGrey,WAVEFORMVIEWX + 1,WAVEFORMVIEWY + 1,
  1605.                     WAVEFORMVIEWWIDTH(WindowWidth) - 2,WAVEFORMVIEWHEIGHT(WindowHeight) - 2);
  1606.                 return;
  1607.             }
  1608.         DrawBoxErase(Window->ScreenID,WAVEFORMVIEWX + 1,WAVEFORMVIEWY + 1,
  1609.             WAVEFORMVIEWWIDTH(WindowWidth) - 2,WAVEFORMVIEWHEIGHT(WindowHeight) - 2);
  1610.         ERROR((Window->CurrentlyVisibleTable < 0) || (Window->CurrentlyVisibleTable
  1611.             >= WaveTableWindowGetNumTables(Window)),PRERR(ForceAbort,
  1612.             "WaveTableWindowRedrawTable:  current table index is out of range"));
  1613.         Limit = WaveTableWindowGetNumFramesPerTable(Window);
  1614.         PreviousYValueIsValid = False;
  1615.         for (Scan = 0; Scan < Limit; Scan += 1)
  1616.             {
  1617.                 double                    Value;
  1618.                 OrdType                    ThisYValue;
  1619.                 OrdType                    ThisXValue;
  1620.  
  1621.                 Value = largefixed2double(WaveTableStorDispGetFrame(Window->WaveTableData,
  1622.                     Window->CurrentlyVisibleTable,Scan));
  1623.                 ThisYValue = (1 - ((Value + 1) / 2)) * (WAVEFORMVIEWHEIGHT(WindowHeight) - 3)
  1624.                     + WAVEFORMVIEWY + 1;
  1625.                 ThisXValue = (Scan * (WAVEFORMVIEWWIDTH(WindowWidth) - 2))
  1626.                     / (Limit - 1) + WAVEFORMVIEWX + 1;
  1627.                 if (!PreviousYValueIsValid)
  1628.                     {
  1629.                         PreviousYValueIsValid = True;
  1630.                         PreviousYValue = ThisYValue;
  1631.                         PreviousXValue = ThisXValue;
  1632.                     }
  1633.                 DrawLine(Window->ScreenID,eBlack,PreviousXValue,PreviousYValue,
  1634.                     ThisXValue - PreviousXValue,ThisYValue - PreviousYValue);
  1635.                 PreviousYValue = ThisYValue;
  1636.                 PreviousXValue = ThisXValue;
  1637.             }
  1638.     }
  1639.  
  1640.  
  1641. /* the name of the file has changed, so change the title bar.  the string is a */
  1642. /* non-null-terminated, and the caller is responsible for disposing of it */
  1643. void                                WaveTableWindowGlobalNameChange(WaveTableWindowRec* Window,
  1644.                                             char* NewFilename)
  1645.     {
  1646.         char*                            LocalNameCopy;
  1647.  
  1648.         CheckPtrExistence(Window);
  1649.         CheckPtrExistence(NewFilename);
  1650.         LocalNameCopy = WaveTableWindowGetNameCopy(Window);
  1651.         if (LocalNameCopy != NIL)
  1652.             {
  1653.                 char*                            SeparatorString;
  1654.  
  1655.                 SeparatorString = StringToBlockCopy(":  ");
  1656.                 if (SeparatorString != NIL)
  1657.                     {
  1658.                         char*                            LeftHalfOfString;
  1659.  
  1660.                         LeftHalfOfString = ConcatBlockCopy(NewFilename,SeparatorString);
  1661.                         if (LeftHalfOfString != NIL)
  1662.                             {
  1663.                                 char*                            TotalString;
  1664.  
  1665.                                 TotalString = ConcatBlockCopy(LeftHalfOfString,LocalNameCopy);
  1666.                                 if (TotalString != NIL)
  1667.                                     {
  1668.                                         char*                            NullTerminatedString;
  1669.  
  1670.                                         NullTerminatedString = BlockToStringCopy(TotalString);
  1671.                                         if (NullTerminatedString != NIL)
  1672.                                             {
  1673.                                                 SetWindowName(Window->ScreenID,NullTerminatedString);
  1674.                                                 ChangeItemName(Window->MyMenuItem,NullTerminatedString);
  1675.                                                 ReleasePtr(NullTerminatedString);
  1676.                                             }
  1677.                                         ReleasePtr(TotalString);
  1678.                                     }
  1679.                                 ReleasePtr(LeftHalfOfString);
  1680.                             }
  1681.                         ReleasePtr(SeparatorString);
  1682.                     }
  1683.                 ReleasePtr(LocalNameCopy);
  1684.             }
  1685.     }
  1686.  
  1687.  
  1688. /* reset the title bar name even if the document name hasn't changed */
  1689. void                                WaveTableWindowResetTitlebar(WaveTableWindowRec* Window)
  1690.     {
  1691.         char*                            DocumentName;
  1692.  
  1693.         CheckPtrExistence(Window);
  1694.         DocumentName = GetCopyOfDocumentName(Window->MainWindow);
  1695.         if (DocumentName != NIL)
  1696.             {
  1697.                 WaveTableWindowGlobalNameChange(Window,DocumentName);
  1698.                 ReleasePtr(DocumentName);
  1699.             }
  1700.     }
  1701.  
  1702.  
  1703. /* set the number of periods to that stored in the edit box, and interpolate */
  1704. /* the periods. */
  1705. void                                WaveTableWindowSetNewNumTables(WaveTableWindowRec* Window)
  1706.     {
  1707.         long                            OriginalNumTables;
  1708.         long                            NewNumTables;
  1709.  
  1710.         CheckPtrExistence(Window);
  1711.         OriginalNumTables = WaveTableWindowGetNumTables(Window);
  1712.         NewNumTables = DoNumberDialog("Enter new number of tables:",OriginalNumTables,
  1713.             mCut,mPaste,mCopy,mUndo,mSelectAll,mClear);
  1714.         if (NewNumTables != OriginalNumTables)
  1715.             {
  1716.                 WaveTableStorDispRec*    NewTable;
  1717.                 long                                    TableScan;
  1718.  
  1719.                 /* free up undo-backup info */
  1720.                 if (Window->UndoBackupWaveTable != NIL)
  1721.                     {
  1722.                         DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  1723.                         Window->UndoBackupWaveTable = NIL;
  1724.                     }
  1725.  
  1726.                 /* build new table */
  1727.                 NewTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(Window->WaveTableData),
  1728.                     WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  1729.                 if (NewTable == NIL)
  1730.                     {
  1731.                      MemoryFailurePoint1:
  1732.                         AlertHalt("There is not enough memory available to resize the wave table.",NIL);
  1733.                         return;
  1734.                     }
  1735.                 for (TableScan = 0; TableScan < NewNumTables; TableScan += 1)
  1736.                     {
  1737.                         if (!WaveTableStorDispAppendEntry(NewTable))
  1738.                             {
  1739.                              MemoryFailurePoint2:
  1740.                                 DisposeWaveTableStorDisp(NewTable);
  1741.                                 goto MemoryFailurePoint1;
  1742.                             }
  1743.                     }
  1744.  
  1745.                 if ((NewNumTables != 0) && (OriginalNumTables != 0))
  1746.                     {
  1747.                         long                        NumFrames;
  1748.  
  1749.                         NumFrames = WaveTableStorDispNumFramesPerTable(NewTable);
  1750.                         /* store the neat things into the table.  we use linear interpolation */
  1751.                         /* between adjacent tables to create new tables. */
  1752.                         for (TableScan = 0; TableScan < NewNumTables; TableScan += 1)
  1753.                             {
  1754.                                 double                        LeftWeight;
  1755.                                 double                        RightWeight;
  1756.                                 long                            LeftIndex;
  1757.                                 long                            RightIndex;
  1758.                                 double                        PrecisePositioning;
  1759.                                 long                            FrameScan;
  1760.  
  1761.                                 if (NewNumTables > 1)
  1762.                                     {
  1763.                                         PrecisePositioning = (double)TableScan / (double)(NewNumTables - 1)
  1764.                                             * (double)(OriginalNumTables - 1);
  1765.                                     }
  1766.                                  else
  1767.                                     {
  1768.                                         PrecisePositioning = (double)(OriginalNumTables - 1) / 2;
  1769.                                     }
  1770.                                 LeftIndex = (long)PrecisePositioning;
  1771.                                 RightIndex = LeftIndex + 1;
  1772.                                 RightWeight = PrecisePositioning - LeftIndex;
  1773.                                 LeftWeight = 1 - RightWeight;
  1774.                                 for (FrameScan = 0; FrameScan < NumFrames; FrameScan += 1)
  1775.                                     {
  1776.                                         double                        LeftValue;
  1777.                                         double                        RightValue;
  1778.                                         double                        ResultantComposite;
  1779.  
  1780.                                         LeftValue = largefixed2double(WaveTableStorDispGetFrame(
  1781.                                             Window->WaveTableData,LeftIndex,FrameScan));
  1782.                                         if (RightIndex < OriginalNumTables)
  1783.                                             {
  1784.                                                 RightValue = largefixed2double(WaveTableStorDispGetFrame(
  1785.                                                     Window->WaveTableData,RightIndex,FrameScan));
  1786.                                             }
  1787.                                          else
  1788.                                             {
  1789.                                                 RightValue = 0;
  1790.                                                 ERROR(RightWeight != 0,PRERR(ForceAbort,
  1791.                                                     "WaveTableWindowSetNewNumTables:  on last table, but right "
  1792.                                                     "weight is non-zero."));
  1793.                                             }
  1794.                                         ResultantComposite = LeftValue * LeftWeight
  1795.                                             + RightValue * RightWeight;
  1796.                                         WaveTableStorDispSetFrame(NewTable,TableScan,FrameScan,
  1797.                                             double2largefixed(ResultantComposite));
  1798.                                     }
  1799.                             }
  1800.                     }
  1801.  
  1802.                 /* save it */
  1803.                 Window->UndoBackupWaveTable = Window->WaveTableData;
  1804.                 Window->WaveTableData = NewTable;
  1805.                 WaveTableWindowUpdateAllParameters(Window);
  1806.                 Window->WaveDataModified = True;
  1807.             }
  1808.     }
  1809.  
  1810.  
  1811. /* set the number of periods edit box to be the same as the data */
  1812. void                                WaveTableWindowUpdateTableCountEdit(WaveTableWindowRec* Window)
  1813.     {
  1814.         char*                            StringTemp;
  1815.  
  1816.         CheckPtrExistence(Window);
  1817.         StringTemp = IntegerToString(WaveTableObjectGetNumTables(Window->WaveTableObject));
  1818.         if (StringTemp == NIL)
  1819.             {
  1820.                 return;
  1821.             }
  1822.         TextEditNewRawData(Window->NumTablesEdit,StringTemp,"\x0a");
  1823.         ReleasePtr(StringTemp);
  1824.         TextEditHasBeenSaved(Window->NumTablesEdit);
  1825.     }
  1826.  
  1827.  
  1828. /* set the number of frames edit box to be the same as the data */
  1829. void                                WaveTableWindowUpdateFrameCountEdit(WaveTableWindowRec* Window)
  1830.     {
  1831.         char*                            StringTemp;
  1832.  
  1833.         CheckPtrExistence(Window);
  1834.         StringTemp = IntegerToString(
  1835.             WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  1836.         if (StringTemp == NIL)
  1837.             {
  1838.                 return;
  1839.             }
  1840.         TextEditNewRawData(Window->NumFramesEdit,StringTemp,"\x0a");
  1841.         ReleasePtr(StringTemp);
  1842.         TextEditHasBeenSaved(Window->NumFramesEdit);
  1843.     }
  1844.  
  1845.  
  1846. /* set all edit boxes to be the same as the underlying data */
  1847. void                                WaveTableWindowUpdateAllParameters(WaveTableWindowRec* Window)
  1848.     {
  1849.         if (Window->CurrentlyVisibleTable
  1850.             > WaveTableObjectGetNumTables(Window->WaveTableObject) - 1)
  1851.             {
  1852.                 Window->CurrentlyVisibleTable
  1853.                     = WaveTableObjectGetNumTables(Window->WaveTableObject) - 1;
  1854.             }
  1855.         if (Window->CurrentlyVisibleTable < 0)
  1856.             {
  1857.                 Window->CurrentlyVisibleTable = 0;
  1858.             }
  1859.         WaveTableWindowUpdateTableCountEdit(Window);
  1860.         WaveTableWindowUpdateFrameCountEdit(Window);
  1861.         WaveTableWindowUpdateScrollBar(Window);
  1862.         WaveTableWindowRedrawTable(Window);
  1863.     }
  1864.  
  1865.  
  1866. /* give a dialog box asking for a new number of frames, and then interpolate all */
  1867. /* of the wave periods. */
  1868. void                                WaveTableWindowSetNewNumFrames(WaveTableWindowRec* Window)
  1869.     {
  1870.         long                            OriginalNumFrames;
  1871.         long                            NewNumFrames;
  1872.         WaveTableStorDispRec*    NewTable;
  1873.         long                            NumberOfTables;
  1874.         long                            TableScan;
  1875.  
  1876.         CheckPtrExistence(Window);
  1877.         OriginalNumFrames = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  1878.         NewNumFrames = AskForNewWaveTableSize(OriginalNumFrames);
  1879.  
  1880.         if (NewNumFrames == OriginalNumFrames)
  1881.             {
  1882.                 return;
  1883.             }
  1884.  
  1885.         /* dump the undo backup information */
  1886.         if (Window->UndoBackupWaveTable != NIL)
  1887.             {
  1888.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  1889.                 Window->UndoBackupWaveTable = NIL;
  1890.             }
  1891.  
  1892.         /* create a new table */
  1893.         NewTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(Window->WaveTableData),
  1894.             NewNumFrames);
  1895.         if (NewTable == NIL)
  1896.             {
  1897.              MemoryFailurePoint1:
  1898.                 AlertHalt("There is not enough memory available to resample the wave table.",NIL);
  1899.                 return;
  1900.             }
  1901.         NumberOfTables = WaveTableStorDispNumTables(Window->WaveTableData);
  1902.         for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1903.             {
  1904.                 if (!WaveTableStorDispAppendEntry(NewTable))
  1905.                     {
  1906.                      MemoryFailurePoint2:
  1907.                         DisposeWaveTableStorDisp(NewTable);
  1908.                         goto MemoryFailurePoint1;
  1909.                     }
  1910.             }
  1911.  
  1912.         /* this one handles interpolating between entries to expand the table */
  1913.         if (NewNumFrames > OriginalNumFrames)
  1914.             {
  1915.                 long                            ExpansionFactor;
  1916.  
  1917.                 ExpansionFactor = NewNumFrames / OriginalNumFrames;
  1918.                 for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1919.                     {
  1920.                         long                            NewFrameScan;
  1921.  
  1922.                         for (NewFrameScan = 0; NewFrameScan < NewNumFrames; NewFrameScan += 1)
  1923.                             {
  1924.                                 double                        LeftWeight;
  1925.                                 double                        RightWeight;
  1926.                                 long                            LeftIndex;
  1927.                                 long                            RightIndex;
  1928.                                 double                        PrecisePositioning;
  1929.                                 double                        LeftValue;
  1930.                                 double                        RightValue;
  1931.                                 double                        ResultantComposite;
  1932.  
  1933.                                 PrecisePositioning = (double)NewFrameScan / (double)NewNumFrames
  1934.                                     * (double)OriginalNumFrames;
  1935.                                 LeftIndex = (long)PrecisePositioning;
  1936.                                 RightIndex = LeftIndex + 1;
  1937.                                 RightWeight = PrecisePositioning - LeftIndex;
  1938.                                 LeftWeight = 1 - RightWeight;
  1939.                                 LeftValue = largefixed2double(WaveTableStorDispGetFrame(
  1940.                                     Window->WaveTableData,TableScan,LeftIndex));
  1941.                                 RightValue = largefixed2double(WaveTableStorDispGetFrame(
  1942.                                     Window->WaveTableData,TableScan,RightIndex % OriginalNumFrames));
  1943.                                 ResultantComposite = LeftValue * LeftWeight
  1944.                                     + RightValue * RightWeight;
  1945.                                 WaveTableStorDispSetFrame(NewTable,TableScan,NewFrameScan,
  1946.                                     double2largefixed(ResultantComposite));
  1947.                             }
  1948.                     }
  1949.             }
  1950.  
  1951.         /* this one handles averaging the frames for table compression */
  1952.         else
  1953.             {
  1954.                 long                            FoldingFactor;
  1955.  
  1956.                 FoldingFactor = OriginalNumFrames / NewNumFrames;
  1957.                 for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1958.                     {
  1959.                         long                            NewFrameScan;
  1960.  
  1961.                         for (NewFrameScan = 0; NewFrameScan < NewNumFrames; NewFrameScan += 1)
  1962.                             {
  1963.                                 double                        Accumulator;
  1964.                                 long                            SumScan;
  1965.                                 double                        Average;
  1966.  
  1967.                                 Accumulator = 0;
  1968.                                 for (SumScan = 0; SumScan < FoldingFactor; SumScan += 1)
  1969.                                     {
  1970.                                         Accumulator += largefixed2double(WaveTableStorDispGetFrame(
  1971.                                             Window->WaveTableData,TableScan,
  1972.                                             NewFrameScan * FoldingFactor + SumScan));
  1973.                                     }
  1974.                                 Average = Accumulator / FoldingFactor;
  1975.                                 WaveTableStorDispSetFrame(NewTable,TableScan,NewFrameScan,
  1976.                                     double2largefixed(Average));
  1977.                             }
  1978.                     }
  1979.             }
  1980.  
  1981.         Window->UndoBackupWaveTable = Window->WaveTableData;
  1982.         Window->WaveTableData = NewTable;
  1983.         WaveTableWindowUpdateAllParameters(Window);
  1984.         Window->WaveDataModified = True;
  1985.     }
  1986.  
  1987.  
  1988. /* argument list for wave table function thang */
  1989. static FunctionParamRec        ArgumentList[] =
  1990.     {
  1991.         {"frames",eInteger},
  1992.         {"tables",eInteger},
  1993.         {"data",eArrayOfFixed}
  1994.     };
  1995. #define ARGLISTLENGTH (sizeof(ArgumentList) / sizeof(ArgumentList[0]))
  1996.  
  1997.  
  1998. /* evaluate the wave formula and update the wave data */
  1999. void                                WaveTableWindowEvaluateFunction(WaveTableWindowRec* Window)
  2000.     {
  2001.         char*                                Blob;
  2002.         PcodeRec*                        FuncCode;
  2003.         CompileErrors                Error;
  2004.         long                                LineNumber;
  2005.         ParamStackRec*            ParamList;
  2006.         EvalErrors                    OtherError;
  2007.         OpcodeRec*                    ErrorOpcode;
  2008.         long                                OffendingInstruction;
  2009.         DataTypes                        ReturnType;
  2010.         long                                TotalFramesPerTable;
  2011.         long                                TotalNumTables;
  2012.  
  2013.         CheckPtrExistence(Window);
  2014.  
  2015.         /* bring the world up to date */
  2016.         if (!MainWindowMakeUpToDateFunctions(Window->MainWindow))
  2017.             {
  2018.                 return;
  2019.             }
  2020.  
  2021.         /* prepare the text blob to be evaluated */
  2022.         Blob = TextEditGetRawData(Window->FunctionEdit,"\x0a");
  2023.         if (Blob == NIL)
  2024.             {
  2025.              FailurePoint1:
  2026.                 AlertHalt("There is not enough memory available to compile the expression.",NIL);
  2027.                 return;
  2028.             }
  2029.  
  2030.         if (Window->UndoBackupWaveTable != NIL)
  2031.             {
  2032.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  2033.                 Window->UndoBackupWaveTable = NIL;
  2034.             }
  2035.  
  2036.         /* perform compilation */
  2037.         Error = CompileSpecialFunction(ArgumentList,ARGLISTLENGTH,&LineNumber,
  2038.             &ReturnType,Blob,&FuncCode);
  2039.         ReleasePtr(Blob);
  2040.         if (Error != eCompileNoError)
  2041.             {
  2042.                 SetTextEditSelection(Window->FunctionEdit,LineNumber - 1,0,LineNumber,0);
  2043.                 TextEditShowSelection(Window->FunctionEdit);
  2044.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  2045.                 return;
  2046.             }
  2047.  
  2048.         /* try to evaluate the code */
  2049.         ParamList = NewParamStack();
  2050.         if (ParamList == NIL)
  2051.             {
  2052.              SecondFailurePoint1:
  2053.                 DisposePcode(FuncCode);
  2054.                 AlertHalt("There is not enough memory available to evaluate the expression.",NIL);
  2055.                 return;
  2056.             }
  2057.         TotalFramesPerTable = WaveTableWindowGetNumFramesPerTable(Window);
  2058.         TotalNumTables = WaveTableWindowGetNumTables(Window);
  2059.         /* add a space for the return value */
  2060.         if (!AddIntegerToStack(ParamList,0))
  2061.             {
  2062.              SecondFailurePoint2:
  2063.                 DisposeParamStack(ParamList);
  2064.                 goto SecondFailurePoint1;
  2065.             }
  2066.         /* frames */
  2067.         if (!AddIntegerToStack(ParamList,TotalFramesPerTable))
  2068.             {
  2069.                 goto SecondFailurePoint2;
  2070.             }
  2071.         /* tables */
  2072.         if (!AddIntegerToStack(ParamList,TotalNumTables))
  2073.             {
  2074.                 goto SecondFailurePoint2;
  2075.             }
  2076.         /* data */
  2077.         {
  2078.             largefixedsigned*        TheDataBlock;
  2079.             long                                TableScan;
  2080.             long                                FrameScan;
  2081.  
  2082.             TheDataBlock = (largefixedsigned*)AllocPtrCanFail(sizeof(largefixedsigned)
  2083.                 * TotalFramesPerTable * TotalNumTables,"WaveTableWindowEvaluateFunction: array");
  2084.             if (TheDataBlock == NIL)
  2085.                 {
  2086.                     goto SecondFailurePoint2;
  2087.                 }
  2088.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2089.                 {
  2090.                     for (FrameScan = 0; FrameScan < TotalFramesPerTable; FrameScan += 1)
  2091.                         {
  2092.                             PRNGCHK(TheDataBlock,&(TheDataBlock[TableScan * TotalFramesPerTable
  2093.                                 + FrameScan]),sizeof(TheDataBlock[TableScan * TotalFramesPerTable
  2094.                                 + FrameScan]));
  2095.                             TheDataBlock[TableScan * TotalFramesPerTable + FrameScan]
  2096.                                 = WaveTableStorDispGetFrame(Window->WaveTableData,TableScan,FrameScan);
  2097.                         }
  2098.                 }
  2099.             if (!AddArrayToStack(ParamList,TheDataBlock))
  2100.                 {
  2101.                     ReleasePtr((char*)TheDataBlock);
  2102.                     goto SecondFailurePoint2;
  2103.                 }
  2104.         }
  2105.  
  2106.         /* executing the actual code */
  2107.         OtherError = EvaluatePcode(ParamList,FuncCode,
  2108.             Window->CodeCenter,&ErrorOpcode,&OffendingInstruction,Window->MainWindow,
  2109.             &MainWindowGetSampleLeftCopy,&MainWindowGetSampleRightCopy,
  2110.             &MainWindowGetSampleMonoCopy,&MainWindowGetWaveTableFrameCount,
  2111.             &MainWindowGetWaveTableTableCount,&MainWindowGetWaveTableArray);
  2112.         if (OtherError != eEvalNoError)
  2113.             {
  2114.                 char*                    FuncNameString;
  2115.                 FuncCodeRec*    ErrorFunction;
  2116.                 MyBoolean            SuccessFlag;
  2117.  
  2118.                 /* present error message */
  2119.                 SuccessFlag = False;
  2120.                 ErrorFunction = GetFunctionFromOpcode(Window->CodeCenter,ErrorOpcode);
  2121.                 if (ErrorFunction == NIL)
  2122.                     {
  2123.                         FuncNameString = StringToBlockCopy("<anonymous>");
  2124.                     }
  2125.                  else
  2126.                     {
  2127.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  2128.                     }
  2129.                 if (FuncNameString != NIL)
  2130.                     {
  2131.                         char*                    Key;
  2132.  
  2133.                         Key = StringToBlockCopy("_");
  2134.                         if (Key != NIL)
  2135.                             {
  2136.                                 char*                    BaseMessage;
  2137.  
  2138.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  2139.                                 if (BaseMessage != NIL)
  2140.                                     {
  2141.                                         char*                    FixedMessage1;
  2142.  
  2143.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  2144.                                         if (FixedMessage1 != NIL)
  2145.                                             {
  2146.                                                 char*                    NumberStr;
  2147.  
  2148.                                                 NumberStr = IntegerToString(OffendingInstruction);
  2149.                                                 if (NumberStr != NIL)
  2150.                                                     {
  2151.                                                         char*                    FixedMessage2;
  2152.  
  2153.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  2154.                                                         if (FixedMessage2 != NIL)
  2155.                                                             {
  2156.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  2157.                                                                 SuccessFlag = True;
  2158.                                                                 ReleasePtr(FixedMessage2);
  2159.                                                             }
  2160.                                                         ReleasePtr(NumberStr);
  2161.                                                     }
  2162.                                                 ReleasePtr(FixedMessage1);
  2163.                                             }
  2164.                                         ReleasePtr(BaseMessage);
  2165.                                     }
  2166.                                 ReleasePtr(Key);
  2167.                             }
  2168.                         ReleasePtr(FuncNameString);
  2169.                     }
  2170.                 if (!SuccessFlag)
  2171.                     {
  2172.                         AlertHalt("There is not enough memory available to show "
  2173.                             "the compile error message.",NIL);
  2174.                     }
  2175.                 DisposeParamStack(ParamList);
  2176.                 DisposePcode(FuncCode);
  2177.                 return;
  2178.             }
  2179.  
  2180.         /* get the data out */
  2181.         {
  2182.             largefixedsigned*            DataBlock;
  2183.             WaveTableStorDispRec*    NewWaveTable;
  2184.             long                                    TableScan;
  2185.             long                                    FrameScan;
  2186.  
  2187.             DataBlock = (largefixedsigned*)GetStackArray(ParamList,3);
  2188.             CheckPtrExistence((char*)DataBlock);
  2189.             NewWaveTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(
  2190.                 Window->WaveTableData),TotalFramesPerTable);
  2191.             if (NewWaveTable == NIL)
  2192.                 {
  2193.                  FinishedSideNoMemory1:
  2194.                     AlertHalt("There is not enough memory available to build the wave.",NIL);
  2195.                     DisposeParamStack(ParamList);
  2196.                     DisposePcode(FuncCode);
  2197.                     return;
  2198.                 }
  2199.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2200.                 {
  2201.                     if (!WaveTableStorDispAppendEntry(NewWaveTable))
  2202.                         {
  2203.                          FinishedSideNoMemory2:
  2204.                             DisposeWaveTableStorDisp(NewWaveTable);
  2205.                             goto FinishedSideNoMemory1;
  2206.                         }
  2207.                 }
  2208.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2209.                 {
  2210.                     for (FrameScan = 0; FrameScan < TotalFramesPerTable; FrameScan += 1)
  2211.                         {
  2212.                             PRNGCHK(DataBlock,&(DataBlock[TableScan * TotalFramesPerTable + FrameScan]),
  2213.                                 sizeof(DataBlock[TableScan * TotalFramesPerTable + FrameScan]));
  2214.                             WaveTableStorDispSetFrame(NewWaveTable,TableScan,FrameScan,
  2215.                                 DataBlock[TableScan * TotalFramesPerTable + FrameScan]);
  2216.                         }
  2217.                 }
  2218.             Window->UndoBackupWaveTable = Window->WaveTableData;
  2219.             Window->WaveTableData = NewWaveTable;
  2220.             Window->WaveDataModified = True;
  2221.         }
  2222.         DisposeParamStack(ParamList); /* disposes our array for us */
  2223.         DisposePcode(FuncCode);
  2224.         WaveTableWindowUpdateAllParameters(Window);
  2225.     }
  2226.  
  2227.  
  2228. /* get a copy of the wave data array */
  2229. largefixedsigned*        WaveTableWindowGetWaveArray(WaveTableWindowRec* Window)
  2230.     {
  2231.         largefixedsigned*    Array;
  2232.         long                            TableLimit;
  2233.         long                            FrameLimit;
  2234.         long                            TableScan;
  2235.  
  2236.         CheckPtrExistence(Window);
  2237.         TableLimit = WaveTableStorDispNumTables(Window->WaveTableData);
  2238.         FrameLimit = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  2239.         Array = (largefixedsigned*)AllocPtrCanFail(TableLimit * FrameLimit
  2240.             * sizeof(largefixedsigned),"WaveTableWindowGetWaveArray");
  2241.         if (Array != NIL)
  2242.             {
  2243.                 for (TableScan = 0; TableScan < TableLimit; TableScan += 1)
  2244.                     {
  2245.                         long                            FrameScan;
  2246.  
  2247.                         for (FrameScan = 0; FrameScan < FrameLimit; FrameScan += 1)
  2248.                             {
  2249.                                 PRNGCHK(Array,&(Array[TableScan * FrameLimit + FrameScan]),
  2250.                                     sizeof(Array[TableScan * FrameLimit + FrameScan]));
  2251.                                 Array[TableScan * FrameLimit + FrameScan]
  2252.                                     = WaveTableStorDispGetFrame(Window->WaveTableData,
  2253.                                     TableScan,FrameScan);
  2254.                             }
  2255.                     }
  2256.             }
  2257.         return Array;
  2258.     }
  2259.  
  2260.  
  2261. /* force the wave data to be written back to the object.  this does not write back */
  2262. /* any other data. */
  2263. MyBoolean                        WaveTableWindowForceWaveTableUpdate(WaveTableWindowRec* Window)
  2264.     {
  2265.         WaveTableStorageRec*        NewWaveTable;
  2266.  
  2267.         CheckPtrExistence(Window);
  2268.  
  2269.         NewWaveTable = NewWaveTableStorage(WaveTableStorDispNumBits(Window->WaveTableData),
  2270.             WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  2271.         if (NewWaveTable != NIL)
  2272.             {
  2273.                 long                                        Limit;
  2274.                 long                                        Scan;
  2275.  
  2276.                 Limit = WaveTableStorDispNumTables(Window->WaveTableData);
  2277.                 for (Scan = 0; Scan < Limit; Scan += 1)
  2278.                     {
  2279.                         long                            Index;
  2280.                         long                            IndexLimit;
  2281.  
  2282.                         if (!WaveTableStorageAppendEntry(NewWaveTable))
  2283.                             {
  2284.                                 DisposeWaveTableStorage(NewWaveTable);
  2285.                                 return False;
  2286.                             }
  2287.                         IndexLimit = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  2288.                         for (Index = 0; Index < IndexLimit; Index += 1)
  2289.                             {
  2290.                                 WaveTableStorageSetFrame(NewWaveTable,Scan,Index,
  2291.                                     WaveTableStorDispGetFrame(Window->WaveTableData,Scan,Index));
  2292.                             }
  2293.                     }
  2294.                 WaveTableObjectPutNewData(Window->WaveTableObject,NewWaveTable);
  2295.                 return True;
  2296.             }
  2297.          else
  2298.             {
  2299.                 return False;
  2300.             }
  2301.     }
  2302.  
  2303.  
  2304. /* force all data to be written back to the object.  this includes calling */
  2305. /* WaveTableWindowForceWaveTableUpdate() */
  2306. MyBoolean                        WaveTableWindowWritebackModifiedData(WaveTableWindowRec* Window)
  2307.     {
  2308.         MyBoolean                    SuccessFlag = True;
  2309.  
  2310.         CheckPtrExistence(Window);
  2311.  
  2312.         if (TextEditDoesItNeedToBeSaved(Window->NameEdit))
  2313.             {
  2314.                 char*                        String;
  2315.  
  2316.                 String = WaveTableWindowGetNameCopy(Window);
  2317.                 if (String != NIL)
  2318.                     {
  2319.                         WaveTableObjectNewName(Window->WaveTableObject,String);
  2320.                         TextEditHasBeenSaved(Window->NameEdit);
  2321.                     }
  2322.                  else
  2323.                     {
  2324.                         SuccessFlag = False;
  2325.                     }
  2326.             }
  2327.  
  2328.         if (TextEditDoesItNeedToBeSaved(Window->FunctionEdit))
  2329.             {
  2330.                 char*                        String;
  2331.  
  2332.                 String = WaveTableWindowGetFormulaCopy(Window);
  2333.                 if (String != NIL)
  2334.                     {
  2335.                         WaveTableObjectNewFormula(Window->WaveTableObject,String);
  2336.                         TextEditHasBeenSaved(Window->FunctionEdit);
  2337.                     }
  2338.                  else
  2339.                     {
  2340.                         SuccessFlag = False;
  2341.                     }
  2342.             }
  2343.  
  2344.         if (TextEditDoesItNeedToBeSaved(Window->TestAttackDuration))
  2345.             {
  2346.                 char*                        String;
  2347.  
  2348.                 String = TextEditGetRawData(Window->TestAttackDuration,SYSTEMLINEFEED);
  2349.                 if (String != NIL)
  2350.                     {
  2351.                         SetWaveTableObjectTestAttack(Window->WaveTableObject,
  2352.                             StringToLongDouble(String,PtrSize(String)));
  2353.                         ReleasePtr(String);
  2354.                         TextEditHasBeenSaved(Window->TestAttackDuration);
  2355.                     }
  2356.                  else
  2357.                     {
  2358.                         SuccessFlag = False;
  2359.                     }
  2360.             }
  2361.  
  2362.         if (TextEditDoesItNeedToBeSaved(Window->TestDecayDuration))
  2363.             {
  2364.                 char*                        String;
  2365.  
  2366.                 String = TextEditGetRawData(Window->TestDecayDuration,SYSTEMLINEFEED);
  2367.                 if (String != NIL)
  2368.                     {
  2369.                         SetWaveTableObjectTestDecay(Window->WaveTableObject,
  2370.                             StringToLongDouble(String,PtrSize(String)));
  2371.                         ReleasePtr(String);
  2372.                         TextEditHasBeenSaved(Window->TestDecayDuration);
  2373.                     }
  2374.                  else
  2375.                     {
  2376.                         SuccessFlag = False;
  2377.                     }
  2378.             }
  2379.  
  2380.         if (TextEditDoesItNeedToBeSaved(Window->TestFrequency))
  2381.             {
  2382.                 char*                        String;
  2383.  
  2384.                 String = TextEditGetRawData(Window->TestFrequency,SYSTEMLINEFEED);
  2385.                 if (String != NIL)
  2386.                     {
  2387.                         SetWaveTableObjectTestPitch(Window->WaveTableObject,
  2388.                             StringToLongDouble(String,PtrSize(String)));
  2389.                         ReleasePtr(String);
  2390.                         TextEditHasBeenSaved(Window->TestFrequency);
  2391.                     }
  2392.                  else
  2393.                     {
  2394.                         SuccessFlag = False;
  2395.                     }
  2396.             }
  2397.  
  2398.         if (TextEditDoesItNeedToBeSaved(Window->TestSamplingRate))
  2399.             {
  2400.                 char*                        String;
  2401.  
  2402.                 String = TextEditGetRawData(Window->TestSamplingRate,SYSTEMLINEFEED);
  2403.                 if (String != NIL)
  2404.                     {
  2405.                         SetWaveTableObjectTestSamplingRate(Window->WaveTableObject,
  2406.                             StringToInteger(String,PtrSize(String)));
  2407.                         ReleasePtr(String);
  2408.                         TextEditHasBeenSaved(Window->TestSamplingRate);
  2409.                     }
  2410.                  else
  2411.                     {
  2412.                         SuccessFlag = False;
  2413.                     }
  2414.             }
  2415.  
  2416.         if (Window->WaveDataModified)
  2417.             {
  2418.                 if (WaveTableWindowForceWaveTableUpdate(Window))
  2419.                     {
  2420.                         Window->WaveDataModified = False;
  2421.                     }
  2422.                  else
  2423.                     {
  2424.                         SuccessFlag = False;
  2425.                     }
  2426.             }
  2427.  
  2428.         return SuccessFlag;
  2429.     }
  2430.